MVVM作为一种架构模式,在Android中的主要落地实践脱离不开两个核心类LiveData和ViewModel。阅读之前需要你具备使用LiveData和ViewModel的基本使用。
有的放矢,带着目的的看这篇文或许你会更有收获。这篇文能帮你解除这些疑惑
ViewModel的职责,在以注重生命周期的方式存储和管理界面相关的数据
public interface ViewModelStoreOwner {
ViewModelStore getViewModelStore();
}
//有删减,伪代码
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
public abstract class ViewModel {
private final Map<String, Object> mBagOfTags = new HashMap<>();
final void clear() {
..
synchronized (mBagOfTags) {
for (Object value : mBagOfTags.values()) {
if (obj instanceof Closeable)
((Closeable) obj).close();
}
}
onCleared();
}
<T> T setTagIfAbsent(String key, T newValue) {
... }
<T> T getTag(String key) {
...}
}
}
通常我们使用
//伪代码
public <T extends ViewModel> T get(Class<T> class){
ViewModel viewModle = viewModelStrore.get(key)
if(viewModel == null){
viewModle = factory.create(class)
viewModelStore.put(key,viewModel);
}
return viewModel
}
flowViewModel = ViewModelProvider(this).get(FlowViewModel::class.*java*)
androidx.lifecycle.ViewModelProvider.DefaultKey
+ modelClass.*canonicalName
"*)OnRequeryFactory
、AndroidViewModelFactory
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner s,Lifecycle.Event e) {
if (e == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
Fragment/Activity都实现了ViewModelStoreOwner接口。当组件生命周期状态切换到ON_DESTORY的的时候就会调用ViewModelStroe的clear()方法。这里有个isChangeingConfigurations()的判断。当因为配置变化导致的Activity重建时不会清除ViewModelStore中的数据,ViewModelStore会在新Activity创建时重新被使用。
当调用其clear()方法的时候,会遍历出内部 Closeable 类型的值调用其close方法。其中viewModelScope作为ViewModel的一个扩展属性,如下
获取 ViewModelScope 的时候,这个 CloseableCoroutineScope 对象会被添加到 ViewModle的成员属性mBagOfTags 这个Map里。同时CloseableCoroutineScope实现了 Closeble 接口。当ViewModle clear的时候被调用到 CoroutineCotext.cancel() 已达到取消协程Job的效果。
在看自动解注册之前先看怎么注册的观察者的
//伪代码有删减
@MainThread
public void observe( LifecycleOwner owner, Observer<? super T> observer) {
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
owner.getLifecycle().addObserver(wrapper);
}
LiveData的Oberver()方法中主要做两件事,
这样这个LifecycleBoundObserver对象就可以同时观察监听LiveData的事件和LifeCycle的事件。这样在对应的LifeCycle的事件里就可以做对应的处理。比如移除从注册,不活跃时不通知回调。
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
...
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (currentState == DESTROYED) {
ObserverWrapper removed = mObservers.remove(observer); //从与LiveData解绑
removed.detachObserver() //与生命周期组件接绑
}
...
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
内部实现也比较简单,主要是依托observer监听了组件生命周期,自身进入决定自身是否是处于active状态。
原因,liveData内部维护了一个版本,当恢复到活跃状态时,如果oberver中版本小于了liveData的版本,才会把最近的值分发非observer进而触发回调方法。liveData中版本会虽然每次新值的设置自动+1,代码如下。也就是说,当observer处于非活跃状态期间,如果liveData没有新值被设定进来,当observer回到活跃状态的时候不会被通知回调。
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
fun postValueIntWorkThread(){
liveData.post(1)
liveData.post(2)
}
LiveData有一个理念,只保留最新值。体现在两点
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;//注释3
mPendingData = NOT_SET;//注释4
}
setValue((T) newValue);
}
};
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;//注释5
mPendingData = value;//注释2处,value赋值给mPendingData
}
if (!postTask) {
//注释1:有值正在分发过程中
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
这段代码比较有意思
1> 注释5处,进入被mDataLock这个monitor划定的临界区;计算出postTask的值,如果postTask为ture说明当前没有等待被分发的值,如果值为false说明有正在被分发的值。
2> 注释2处,无论postTask的值为true或者false,都会把value的值赋值给mPendingData。
3 >注释3处,如果有正在分发的值,就不执行接下来的操作了。此时注释2处已经把值赋值给了mPendingData,这个mPending还能分发吗?
4>注释3处这段逻辑通过handler机制,最终在Main线程中执行,把mPendingData赋值给newValue,最终newValue被分发出去了
上面这个步骤下来,思考这样一种情况,连续post 1和2两个值,当post 2的时候,如果此时mPendingData值还为1,那么postTask就为false。但还是把值赋值给了mPendingData。接下来,注释1处正好符合判断条件,就不会向下执行。 当主线程执行到注释3处的runable时,会把2复制给newValue,最后把值分发出去了。
本文主要围绕ViewModel和LiveData一些特性以及内部实现展开,阅读完之后,开头的那几个问题能找到答案了吗?