Kotlin

08 项目架构-MVVM-2

2021-11-16  本文已影响0人  凤邪摩羯

前言

MVVM作为一种架构模式,在Android中的主要落地实践脱离不开两个核心类LiveData和ViewModel。阅读之前需要你具备使用LiveData和ViewModel的基本使用。

有的放矢,带着目的的看这篇文或许你会更有收获。这篇文能帮你解除这些疑惑

1)ViewModel

ViewModel的职责,在以注重生命周期的方式存储和管理界面相关的数据

1.1) ViewModel 特性

1.1.1)注重生命周期

1.1.2) ViewModel相关类

image.png
a) ViewModelStoreOwner
public interface ViewModelStoreOwner {
    ViewModelStore getViewModelStore();
}
复制代码
b) ViewModelStore
//有删减,伪代码
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();
    }
}
复制代码
c) ViewModel
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) { ...}
    }
}
复制代码

1.2)ViewModel 的构建

通常我们使用

//伪代码
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*)
复制代码

1.3) ViewModel 与 Kotlin 的 Coroutine 结合

image.png
getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner s,Lifecycle.Event e) {
                if (e == Lifecycle.Event.ON_DESTROY) {
                    if (!isChangingConfigurations()) {
                        getViewModelStore().clear();
                    }
                }
复制代码

2) LiveData

image.png

2.1 ) 自动解注册是怎么实现的?

在看自动解注册之前先看怎么注册的观察者的

 //伪代码有删减
 @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);
        }
    }
复制代码

2.2)观察者活跃时才响应是怎么回事?

内部实现也比较简单,主要是依托observer监听了组件生命周期,自身进入决定自身是否是处于active状态。

原因,liveData内部维护了一个版本,当恢复到活跃状态时,如果oberver中版本小于了liveData的版本,才会把最近的值分发非observer进而触发回调方法。liveData中版本会虽然每次新值的设置自动+1,代码如下。也就是说,当observer处于非活跃状态期间,如果liveData没有新值被设定进来,当observer回到活跃状态的时候不会被通知回调。

protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}
复制代码

2.3) 子线程中连续多次向LiveData发送值,observer能接受到所有的值吗?

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);
    }
复制代码

这段代码比较有意思

上面这个步骤下来,思考这样一种情况,连续post 1和2两个值,当post 2的时候,如果此时mPendingData值还为1,那么postTask就为false。但还是把值赋值给了mPendingData。接下来,注释1处正好符合判断条件,就不会向下执行。 当主线程执行到注释3处的runable时,会把2复制给newValue,最后把值分发出去了。

上一篇下一篇

猜你喜欢

热点阅读