ViewModel解析

一、简单介绍下ViewModel有什么作用和优点

二、类图总结ViewModel原理

有错漏之处 请多多指教。

ViewModel作用

通常与LiveData一起使用,

(1)将activity, fragment里关于数据操作的逻辑抽离出来,封装到ViewModel中,所以ViewMoel 持有一个成员变量LiveData<T>。

(2)数据的操作包括什么呢? a. 从DB和缓存读取数据,显示到UI;  b. 通过网络到后台拉取数据,持久化到本地,更新DB和缓存,通知UI刷新。

(3)因此ViewModel 应该持有一个 成员变量Repository(相当于一个管理类, 命名可以命名为其他如XXXManager),做(2)的事情。 而组件activity, fragment应该持有一个成员变量ViewModel , 如图所示

图片来源LiveData + ViewModel + Room (Google 官文)+Demo - 简书   

demo地址:MVVM: ViewModel+LiveData+DataBinding+Retrofit+Room+Paging+RxJava 总结与实践(Java实现)_xiaobaaidaba123的专栏-CSDN博客

ViewModel优点

1. 当横竖屏发生切换时,activity会重建,但是ViewModel不需要重建。

2. ViewModel可以避免内存泄漏问题,Activity destroy时会调用ViewModel的onCleared()方法。

3. 可以解决同一个Activity的不同Fragment的数据共享问题。

ViewModel 原理学习总结

 【架构类图】一个图总结

【ViewModelProvider】一两句话总结

1) ViewModelProvider持有两个成员变量 ViewModerStore ——存储ViewModel  和 Factory —— 创建ViewModel。

因此了解ViewModelProvider 的职责——可以把它看成一个wrapper——打包了创建ViewModel和存储ViewModel的功能。

public class ViewModelProvider {
 
    private static final String DEFAULT_KEY =
            "android.arch.lifecycle.ViewModelProvider.DefaultKey";
 
    /**
     **************************************************
     *  ViewModelProvider持有的两个成员变量
     **************************************************
     */
    private final Factory mFactory;
    private final ViewModelStore mViewModelStore;
 
 
    /**
     **************************************************
     * 实现Factory接口来创建ViewModel
     **************************************************
     */
    public interface Factory {
        <T extends ViewModel> T create(Class<T> modelClass);
    }
 
 
    /**
     **************************************************
     *  ViewModelProvider构建方法
     *  参数 ViewModelStoreOwner 和 Factory
     *  ViewModelStoreOwner  是一个接口,可以返回ViewModelStore
     **************************************************
     */
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
        this(owner.getViewModelStore(), factory);
    }
 
    /**
     **************************************************
     *  ViewModelProvider构建方法
     *  参数 ViewModelStore 和 Factory
     **************************************************
     */
    public ViewModelProvider(ViewModelStore store, Factory factory) {
        mFactory = factory;
        this.mViewModelStore = store;
    }
 
    /**
     **************************************************
     * 先获取modelclass名字,再调用get (key, modelclass) 获取ViewModel
     **************************************************
     */
    public <T extends ViewModel> T get(Class<T> modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        if (canonicalName == null) {
            throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
        }
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
 
    /**
     **************************************************
     * 通过key值从ViewModelStore 中获取ViewModel, 如果没有,则通过factory构建一个,再存储到
     * ViewModelStore
     **************************************************
     */
    @NonNull
    @MainThread
    public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);
 
        if (modelClass.isInstance(viewModel)) {
            //noinspection unchecked
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
 
        viewModel = mFactory.create(modelClass);
        mViewModelStore.put(key, viewModel);
        //noinspection unchecked
        return (T) viewModel;
    }
 
    /**
     **************************************************
     *  该工厂类  通过java反射构建ViewModel 调用无参构造方法
      **************************************************
     */
    public static class NewInstanceFactory implements Factory {
 
        @Override
        public <T extends ViewModel> T create(Class<T> modelClass) {
            //noinspection TryWithIdenticalCatches
            try {
                return modelClass.newInstance();
            } catch (InstantiationException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            }
        }
    }
}


【ViewModelStore】一两句话总结

1)ViewModelStore作用很简单——内部持有一个HashMap,存储ViewModel
 

public class ViewModelStore {
 
    /**
     **************************************************
     *  hash map存储viewModel
     **************************************************
     */
    private final HashMap<String, ViewModel> mMap = new HashMap<>();
 
     /**
     **************************************************
     *  put方法
     **************************************************
     */
 
    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.get(key);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
        mMap.put(key, viewModel);
    }
 
     /**
     **************************************************
     *  get方法 
     **************************************************
     */
 
    final ViewModel get(String key) {
        return mMap.get(key);
    }
 
    /**
     **************************************************
     *  清除hashMap
     **************************************************
     */
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.onCleared();
        }
        mMap.clear();
    }
}

 横竖屏切换,为什么ViewModel不会重建

 1)Activity销毁前,先把ViewModelStore保存起来

    @Override
    @Nullable
    public final Object onRetainNonConfigurationInstance() {
        Object custom = onRetainCustomNonConfigurationInstance();
 
        ViewModelStore viewModelStore = mViewModelStore;
        if (viewModelStore == null) {
            // No one called getViewModelStore(), so see if there was an existing
            // ViewModelStore from our last NonConfigurationInstance
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                viewModelStore = nc.viewModelStore;
            }
        }
 
        if (viewModelStore == null && custom == null) {
            return null;
        }
 
        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = viewModelStore;
        return nci;
    }

 2)Activity 重建后调用getViewModelStore()

猜你喜欢

转载自blog.csdn.net/u013773608/article/details/129390520