Android架构——ViewModel原理学习总结

本文是楼主学习ViewModel 源码的一些总结,感觉ViewModel的源码是Android 三大架构中 最容易理解的一个了。本文ViewModel基于版本androidx.lifecycle:lifecycle-viewmodel:2.2.0

本文内容结构

一、简单介绍下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()

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值