Android JetPack——ViewModel原理

ViewModel的作用

MVVM框架的主要组件

ViewModel一般跟LiveData组合使用

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

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

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

ViewModel优点

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

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

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

ViewModel 原理学习总结

ViewModel的创建自然是由ViewModelProvider创建的。

【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保存起来

 2)Activity 重建后调用getViewModelStore()


版权声明:本文为qq_24550911原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。