Lifecycle,LifecycleOwner,LiveData如何監(jiān)聽Activity生命周期?

Lifecycle是一個抽象類,里面有2個枚舉類:
1.Event,對應(yīng)Activity生命周期的各個方法
2.State,記錄當(dāng)前處于什么狀態(tài)

public abstract class Lifecycle {

    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    @NonNull
    AtomicReference<Object> mInternalScopeRef = new AtomicReference<>();

    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);

    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);

    @MainThread
    @NonNull
    public abstract State getCurrentState();

    @SuppressWarnings("WeakerAccess")
    public enum Event {
        
        ON_CREATE,
       
        ON_START,
        
        ON_RESUME,
        
        ON_PAUSE,
     
        ON_STOP,
       
        ON_DESTROY,
 
        ON_ANY
    }

    @SuppressWarnings("WeakerAccess")
    public enum State {
        
        DESTROYED,

        INITIALIZED,

        CREATED,

        STARTED,

        RESUMED;

        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }
}

LifecycleOwner 只是一個接口

@SuppressWarnings({"WeakerAccess", "unused"})
public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     *
     * @return The lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

來看看哪些Activity實(shí)現(xiàn)了這個接口

public class FragmentActivity  extends ComponentActivity 
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner
public class ComponentActivity extends Activity implements
        LifecycleOwner

可以看到FragmentActivity繼承自ComponentActivity ,等于實(shí)現(xiàn)了LifecycleOwner
在ComponentActivity 中有一個成員變量

    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

在ComponentActivity 的getLifecycle便是返回的這個變量

 @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

這里我們先看下LiveData平時是如何在Activity中使用的。

homeViewModel.getIsMineSel().observe(this, aBoolean -> {
            if (aBoolean) {
             xxxxxx
            } 
        });

在LiveData中的observe方法如下

 @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

也就是說LiveData的注冊監(jiān)聽器的方法,實(shí)際上是通過 owner.getLifecycle().addObserver(wrapper);來實(shí)現(xiàn),即是通過這個LifecycleRegistry 的(@NonNull LifecycleObserver observer); LifecycleRegistry 就是繼承了Lifecycle ,

public class LifecycleRegistry extends Lifecycle {

    /**
     * Custom list that keeps observers and can handle removals / additions during traversal.
     *
     * Invariant: at any moment of time for observer1 & observer2:
     * if addition_order(observer1) < addition_order(observer2), then
     * state(observer1) >= state(observer2),
     */
    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();
    /**
     * Current state
     */
    private State mState;
    
    private final WeakReference<LifecycleOwner> mLifecycleOwner;

    private int mAddingObserverCounter = 0;

    private boolean mHandlingEvent = false;
    private boolean mNewEventOccurred = false;

    private ArrayList<State> mParentStates = new ArrayList<>();

    public LifecycleRegistry(@NonNull LifecycleOwner provider) {
        mLifecycleOwner = new WeakReference<>(provider);
        mState = INITIALIZED;
    }

    @Deprecated
    @MainThread
    public void markState(@NonNull State state) {
        setCurrentState(state);
    }

    @MainThread
    public void setCurrentState(@NonNull State state) {
        moveToState(state);
    }

    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }

    private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        mState = next;
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;
        sync();
        mHandlingEvent = false;
    }

    private boolean isSynced() {
        if (mObserverMap.size() == 0) {
            return true;
        }
        State eldestObserverState = mObserverMap.eldest().getValue().mState;
        State newestObserverState = mObserverMap.newest().getValue().mState;
        return eldestObserverState == newestObserverState && mState == newestObserverState;
    }

    private State calculateTargetState(LifecycleObserver observer) {
        Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);

        State siblingState = previous != null ? previous.getValue().mState : null;
        State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
                : null;
        return min(min(mState, siblingState), parentState);
    }

    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }

    private void popParentState() {
        mParentStates.remove(mParentStates.size() - 1);
    }

    private void pushParentState(State state) {
        mParentStates.add(state);
    }

    @Override
    public void removeObserver(@NonNull LifecycleObserver observer) {
        mObserverMap.remove(observer);
    }

    @SuppressWarnings("WeakerAccess")
    public int getObserverCount() {
        return mObserverMap.size();
    }

    @NonNull
    @Override
    public State getCurrentState() {
        return mState;
    }

    static State getStateAfter(Event event) {
        switch (event) {
            case ON_CREATE:
            case ON_STOP:
                return CREATED;
            case ON_START:
            case ON_PAUSE:
                return STARTED;
            case ON_RESUME:
                return RESUMED;
            case ON_DESTROY:
                return DESTROYED;
            case ON_ANY:
                break;
        }
        throw new IllegalArgumentException("Unexpected event value " + event);
    }

    private static Event downEvent(State state) {
        switch (state) {
            case INITIALIZED:
                throw new IllegalArgumentException();
            case CREATED:
                return ON_DESTROY;
            case STARTED:
                return ON_STOP;
            case RESUMED:
                return ON_PAUSE;
            case DESTROYED:
                throw new IllegalArgumentException();
        }
        throw new IllegalArgumentException("Unexpected state value " + state);
    }

    private static Event upEvent(State state) {
        switch (state) {
            case INITIALIZED:
            case DESTROYED:
                return ON_CREATE;
            case CREATED:
                return ON_START;
            case STARTED:
                return ON_RESUME;
            case RESUMED:
                throw new IllegalArgumentException();
        }
        throw new IllegalArgumentException("Unexpected state value " + state);
    }

    private void forwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
                mObserverMap.iteratorWithAdditions();
        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                pushParentState(observer.mState);
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();
            }
        }
    }

    private void backwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
                mObserverMap.descendingIterator();
        while (descendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                Event event = downEvent(observer.mState);
                pushParentState(getStateAfter(event));
                observer.dispatchEvent(lifecycleOwner, event);
                popParentState();
            }
        }
    }

    // happens only on the top of stack (never in reentrance),
    // so it doesn't have to take in account parents
    private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                    + "garbage collected. It is too late to change lifecycle state.");
        }
        while (!isSynced()) {
            mNewEventOccurred = false;
            // no need to check eldest for nullability, because isSynced does it for us.
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                backwardPass(lifecycleOwner);
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

    static State min(@NonNull State state1, @Nullable State state2) {
        return state2 != null && state2.compareTo(state1) < 0 ? state2 : state1;
    }

    static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }
}

問題來了,那么,LiveData是怎么做到監(jiān)聽Activity生命周期,LifecycleRegistry是怎么監(jiān)聽到Activity生命周期的。

關(guān)鍵要看ComponentActivity的onCreate方法,里面調(diào)用了個 ReportFragment.injectIfNeededIn(this);這個ReportFragment就是監(jiān)聽生命周期的關(guān)鍵所在

   protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.mSavedStateRegistryController.performRestore(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
        if (this.mContentLayoutId != 0) {
            this.setContentView(this.mContentLayoutId);
        }
    }

ReportFragment.injectIfNeededIn(this)這個方法的實(shí)現(xiàn)如下,這邊是在activity中注冊了個ActivityLifecycleCallbacks

public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            // On API 29+, we can register for the correct Lifecycle callbacks directly
            activity.registerActivityLifecycleCallbacks(
                    new Application.ActivityLifecycleCallbacks() {
                        @Override
                        public void onActivityCreated(@NonNull Activity activity,
                                @Nullable Bundle bundle) {
                        }

                        @Override
                        public void onActivityPostCreated(@NonNull Activity activity,
                                @Nullable Bundle savedInstanceState) {
                            dispatch(activity, Lifecycle.Event.ON_CREATE);
                        }

                        @Override
                        public void onActivityStarted(@NonNull Activity activity) {
                        }

                        @Override
                        public void onActivityPostStarted(@NonNull Activity activity) {
                            dispatch(activity, Lifecycle.Event.ON_START);
                        }

                        @Override
                        public void onActivityResumed(@NonNull Activity activity) {
                        }

                        @Override
                        public void onActivityPostResumed(@NonNull Activity activity) {
                            dispatch(activity, Lifecycle.Event.ON_RESUME);
                        }

                        @Override
                        public void onActivityPrePaused(@NonNull Activity activity) {
                            dispatch(activity, Lifecycle.Event.ON_PAUSE);
                        }

                        @Override
                        public void onActivityPaused(@NonNull Activity activity) {
                        }

                        @Override
                        public void onActivityPreStopped(@NonNull Activity activity) {
                            dispatch(activity, Lifecycle.Event.ON_STOP);
                        }

                        @Override
                        public void onActivityStopped(@NonNull Activity activity) {
                        }

                        @Override
                        public void onActivitySaveInstanceState(@NonNull Activity activity,
                                @NonNull Bundle bundle) {
                        }

                        @Override
                        public void onActivityPreDestroyed(@NonNull Activity activity) {
                            dispatch(activity, Lifecycle.Event.ON_DESTROY);
                        }

                        @Override
                        public void onActivityDestroyed(@NonNull Activity activity) {
                        }
                    });
        }

在activity中維護(hù)了 一個ArrayList,這個ArrayList就是記錄了ActivityLifecycleCallbacks,觀察者模式就是這里。

private final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
            new ArrayList<Application.ActivityLifecycleCallbacks>();

舉個例子看下Activity執(zhí)行onStart方法時會做什么

 protected void onStart() {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
        mCalled = true;

        mFragments.doLoaderStart();

        dispatchActivityStarted();

        if (mAutoFillResetNeeded) {
            getAutofillManager().onVisibleForAutofill();
        }
    }

   private void dispatchActivityStarted() {
        getApplication().dispatchActivityStarted(this);
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStarted(this);
            }
        }
    }
    private void dispatchActivityPostStarted() {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((Application.ActivityLifecycleCallbacks) callbacks[i])
                        .onActivityPostStarted(this);
            }
        }
        getApplication().dispatchActivityPostStarted(this);
    }


      private Object[] collectActivityLifecycleCallbacks() {
        Object[] callbacks = null;
        synchronized (mActivityLifecycleCallbacks) {
            if (mActivityLifecycleCallbacks.size() > 0) {
                callbacks = mActivityLifecycleCallbacks.toArray();
            }
        }
        return callbacks;
    }

可以看到,activity調(diào)用生命周期回調(diào)方法onStart的時候會去遍歷mActivityLifecycleCallbacks,然后調(diào)用callback的onActivityStarted方法。這就是監(jiān)聽了activity的聲明周期方法,現(xiàn)在回頭看看ReportFragment里的
方法, onActivityStarted是空實(shí)現(xiàn),onActivityPostStarted里面才分發(fā)了onstart生命周期事件。

                        public void onActivityStarted(@NonNull Activity activity) {
                        }
                     @Override
                        public void onActivityPostStarted(@NonNull Activity activity) {
                            dispatch(activity, Lifecycle.Event.ON_START);
                        }

這個和Activity的啟動流程有關(guān)系,Activity.performResume->performRestart->performStart->dispatchActivityPostStarted();-> dispatchActivityPostStarted();這個不影響,大概意思就是通過注冊了Application.ActivityLifecycleCallbacks,通過觀察者模式實(shí)現(xiàn)監(jiān)聽回調(diào)

private void dispatchActivityPostStarted() {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((Application.ActivityLifecycleCallbacks) callbacks[i])
                        .onActivityPostStarted(this);
            }
        }
        getApplication().dispatchActivityPostStarted(this);
    }

接著往下看在ReportFragment中的onActivityPostCreated方法中繼續(xù)分發(fā)事件,可以看到最終是調(diào)用了((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);來繼續(xù)分發(fā)事件的

                    @Override
                        public void onActivityPostStarted(@NonNull Activity activity) {
                            dispatch(activity, Lifecycle.Event.ON_START);
                        }

           @SuppressWarnings("deprecation")
            static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
                if (activity instanceof LifecycleRegistryOwner) {
                    ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
                    return;
                }

                if (activity instanceof LifecycleOwner) {
                    Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
                    if (lifecycle instanceof LifecycleRegistry) {
                        ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
                    }
                }
            }

回頭看上面LifecycleRegistry的源碼,我們可以發(fā)現(xiàn)lifecycleRegistry.handleLifecycleEvent執(zhí)行流程是

handleLifecycleEvent()->moveToState()->sync()->
根據(jù)判斷調(diào)用
backwardPass(lifecycleOwner);->observer.dispatchEvent(lifecycleOwner, event);
或者
forwardPass(lifecycleOwner);->  observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
最終走到
 void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }

這個 mLifecycleObserver.onStateChanged(owner, event);,就是我們 調(diào)用Livdedata.observe方法的時候, 在public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) 的方法里,將我們寫好的回調(diào),包裝成了LifecycleBoundObserver,傳遞給了owner.getLifecycle().addObserver方法

  LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
         ***其他的不管***
        owner.getLifecycle().addObserver(wrapper);

LifecycleBoundObserver類是LiveData的內(nèi)部類:也就是說,最終調(diào)用 mLifecycleObserver.onStateChanged(owner, event);方法,我們要在LiveData的內(nèi)部類LifecycleBoundObserver中看onStateChanged的回調(diào)實(shí)現(xiàn)

   class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }

        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

activeStateChanged(shouldBeActive());方法在LifecycleBoundObserver 的父類ObserverWrapper 中,


    private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

最終方法執(zhí)行到 dispatchingValue(this);里

 @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

這個方法最核心的地方就是調(diào)用了considerNotify(initiator)方法。

  @SuppressWarnings("unchecked")
    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
        //
        // we still first check observer.active to keep it as the entrance for events. So even if
        // the observer moved to an active state, if we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

看到最后一句代碼 observer.mObserver.onChanged((T) mData);,這個onChange回調(diào),就是我們給LiveData對象添加回調(diào)的時候?qū)懙幕卣{(diào)方法,

總結(jié)一下:
通過CompentActivity中的ReportFragment,注冊了監(jiān)聽activity的生命周期回調(diào)方法,然后分發(fā)事件交給LifecycleRegistry的handleLifecycleEvent處理,經(jīng)過一系列判斷,執(zhí)行到observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));——》走mLifecycleObserver.onStateChanged(owner, event);回調(diào),在LiveData里有個內(nèi)部類實(shí)現(xiàn)了這個回調(diào)接口,在我們使用livedata.observer方法的時候已經(jīng)將傳入的回調(diào)包裝成了LifecycleBoundObserver對象,最終通過這個類的父類ObserverWrapper 的onStateChanged——>執(zhí)行了dispatchingValue方法——>considerNotify方法,最終執(zhí)行了傳入給livedata.observer方法的回調(diào)對象的onChanged。
這就是activity生命周期,和LifecycleRegistry(Lifecycle的子類),LiveData對象如何綁定的關(guān)鍵代碼,基本原理還是觀察者模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容