Android Jetpack 三件套 Lifecycke ViewModel LiveData

Android Jetpack 三件套 Lifecycke ViewModel LiveData

2024-06-27
暂无分类

LifeCycle

原理:Activity中添加了一个ReportFragment,在fragment的生命周期方法体内调用handleLifecycleEvent,利用反射机制找到对应的注解,执行方法

// ComponentActivity实现了LifecycleOwner接口
public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     *
     * @return The lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

// 具体内容
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
public Lifecycle getLifecycle() {
    return mLifecycleRegistry;
}

ViewModel

Activity实现了ViewModelStoreOwner接口

public interface ViewModelStoreOwner {
    /**
     * Returns owned {@link ViewModelStore}
     *
     * @return a {@code ViewModelStore}
     */
    @NonNull
    ViewModelStore getViewModelStore();
}

// 实现方法
public ViewModelStore getViewModelStore() {
    if (getApplication() == null) {
        throw new IllegalStateException("Your activity is not yet attached to the "
                + "Application instance. You can't request ViewModel before onCreate call.");
    }
    ensureViewModelStore();
    return mViewModelStore;
}

void ensureViewModelStore() {
    if (mViewModelStore == null) {
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            // Restore the ViewModelStore from NonConfigurationInstances
            mViewModelStore = nc.viewModelStore;
        }
        if (mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
    }
}
getLifecycle().addObserver(new LifecycleEventObserver() {
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        if (event == Lifecycle.Event.ON_DESTROY) {
            // Clear out the available context
            mContextAwareHelper.clearAvailableContext();
            // configchange情况下,不清除viewmodel
            if (!isChangingConfigurations()) {
                getViewModelStore().clear();
            }
        }
    }
});

ViewModelStore内部是个HashMap<String, ViewModel>,key重名时,ViewModel会被覆盖,旧的ViewModel被clear。

ViewModel有个onCleared方法,在ViewModel被销毁时可以进行一些资源清理工作

ViewModelProvider.Factory,主要的功能是用反射机制创建ViewModel实例,ViewModel实例被创建后,只有当ViewModelStoreOwner接口对象DESTORY之后,才会回收。

当你在 Activity 或 Fragment 中使用 by viewModels() 或 ViewModelProvider 来获取 ViewModel 实例时,将其添加到 ViewModelStore 中。

ViewModelStore到底保存到哪里了? 在Activity销毁时,ActivityThread.performDestoryActivity(ActivityClientRecord r,......),其中有r.lastNonConfigurationInstances = retainNonConfigurationInstances(),最后存储在了ActivityClientRecord中,在Activity重建时,通过attach方法,赋值给 mLastNonConfigurationInstances,这样最终就可以获取到之前的viewmodel了

getLifecycle().addObserver(new LifecycleEventObserver() {
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
            // 默认情况下,第一个状态应该是ON_CREATE,所以可以得出结论,ViewModelStore应该是在onCreate()之后被创建的
        ensureViewModelStore();
        getLifecycle().removeObserver(this);
    }
});

viewModelScope原理

public val ViewModel.viewModelScope: CoroutineScope
    get() {
        val scope: CoroutineScope? = this.getTag(JOB_KEY)
        if (scope != null) {
            return scope
        }
        // 向mBagOfTags添加一个Key为JOB_KEY,value为CloseableCoroutineScope的元素
        return setTagIfAbsent(
            JOB_KEY,
            CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
        )
    }

internal class CloseableCoroutineScope(context: CoroutineContext) : Closeable, CoroutineScope {
    override val coroutineContext: CoroutineContext = context

    // activity 或 fragment 处于 DESTORY状态时,会被调用
    override fun close() {
        coroutineContext.cancel()
    }
}

遗留问题

  • getDefaultViewModelCreationExtras是干嘛用的

onSaveInstanceState

onSaveInstanceState干了什么?

protected void onSaveInstanceState(@NonNull Bundle outState) {
    // 保存视图状态(focus,输入框......)
    outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());

    // 保存Fragment状态
    Parcelable p = mFragments.saveAllState();
    if (p != null) {
        outState.putParcelable(FRAGMENTS_TAG, p);
    }
    getAutofillClientController().onSaveInstanceState(outState);
    dispatchActivitySaveInstanceState(outState);
}

什么时候会执行onSaveInstanceState和onRestoreInstanceState

  • 在安卓3.0版本以前,OnSaveInstanceState方法在onPause之前执行

  • 在安卓3.0至安卓9.0版本中,如果是未经许可时销毁则OnSaveInstanceState方法在onPause之后,onStop之前执行

  • 在安卓9.0之后,如果是未经许可时销毁OnSaveInstanceState方在onStop之后执行

  • OnRestoreInstanceState会在onStart之后执行

场景:按HOME键、切换到其他应用、横竖屏切换

onSaveInstanceState和viewmodel区别

  1. onSaveInstanceState 用Bundle存储数据便于跨进程传递,而ViewModel 是Object存储数据,不需要跨进程,因此它没有大小限制。
  2. onSaveInstanceState 在onStop 之后调用,比较频繁。而ViewModel 存储数据是onDestroy 之后。
  3. onSaveInstanceState 可以选择是否持久化数据到文件里(该功能由ATM 实现,存储到xml里),而ViewModel 没有这功能。

LiveData

多次调用postValue导致数据丢失,原因:mPendingData被赋值后,mPostValueRunnable被post到主线程。等待执行的过程中,postValue被再次调用就会return。解决办法,在主线程调用postValue或者setValue

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

粘性数据问题,即在其他地方注册监听时,会收到最后一次发送的数据

// LiveData注册监听
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    
    ...... 

    // 继续看一下LifecycleRegistry的addObserver()干了什么
    owner.getLifecycle().addObserver(wrapper);
}

// LifecycleRegistry注册监听
public void addObserver(@NonNull LifecycleObserver observer) {
    // 给observer设置初始状态,DESTROYED 或者 INITIALIZED。只要不是在onCreate函数中注册的observer,添加的时候都会触发onStateChange回调
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    // 然后把带初始状态的observer添加到mObserverMap中
    ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

    ......
    
    // 同步状态
    sync()
}

private void sync() {
    // 把当前的State与mObserverMap中所有的observer的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);
        }
        Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

// 最后会执行LiveData中的LifecycleBoundObserver的onStateChanged函数
// 最后又调用了LiveData中的considerNotify函数

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) {
        // 核心原因发生在这里,新创建的observer实例,mLastVersion默认是-1,mVersion肯定大于-1,所以就无法return
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

解决办法:添加监听前,用反射修改mVersion的值;开源库UnPeek-LiveData就是在添加监听的时候,直接传入当前的version;用Flow代替

THE END
0/500
暂无评论