IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android之MVVM架构:ViewModel -> 正文阅读

[移动开发]Android之MVVM架构:ViewModel

前言

说起Android开发架构模式,相信很多人都不陌生,一般都能说的上来MVP,MVC,MVVM等架构模式,说起他们的区别,大多数人也能说出一二,无非是不同层之间的解耦,保持的职责单一的开发原则,增强其可扩展性等方便。
而今天要说到的,就是MVVM架构开发模式以及ViewModel的功能组件。

基本使用

  1. 引用ViewModel
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'
  1. 自定义的VM类只要继承引用的第三方库中的ViewModel抽象类即可
class MyViewModel: VideModel{
}
  1. 然后我们就可以在activity/fragment中实例化它
viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
// 这里需要提到一下在旧版本的APIVIewModelProviders已经被添加了Deprecated标签,也就是已经不推荐使用了

viewModel = ViewModelProvider(this).get(MyViewModel::class.java)

Tip:为什么Google抛弃了ViewModelProviders的构造方法,而换成了新的API。
原因是由于以往开发中通过依赖lifecycle-extensions库,间接的依赖了lifecycle-viewmodel库及相关系列库。随着JetPack组件的升级,lifecycle库也将拆分的更加低耦合,可以在某种程度,减少包体体积。

生命周期

在这里插入图片描述
Google官方给的生命周期图

  1. 生命周期长于Activity。不难发现,ViewModel的生命周期,贯穿整个被绑定的Activity的生命周期,也就是说,既然Activity因为系统配置变更销毁重建,比如旋转屏幕等,ViewModel对象依旧会被保留,并关联到新的Activity。只有当Activity正常销毁时,ViewModel对象才会调用onCleared()进行清除。
  2. 开头说过,众多开发模式当中,他们的区别大同小异,都是为了实现解耦。而我们知道,在MVP的Presenter中,需要持有View的接口对象,来回调结果给界面。而ViewModel是不需要持有UI层的引用,由于ViewModel贯穿了Activity的整个完整的生命周期,甚至比Activity生命周期要长,这就导致,如果让ViewModel持有Activity的引用时,容易造成内存泄漏等问题。

Tip:当ViewModel一定需要context引用,有没有什么办法呢? 其实是有的, ViewModel抽象类有一个实现类AndroidViewModel(Application),它接收的对象是application。

分析

我们知道ViewModel能在Activity和Fragment里使用,因此也能作为媒介使得Activity和Fragment进行交互。那么需要在View里使用呢?
假如我有一个自定义view或者dialog,它包含一堆数据和状态,能否使用ViewModel去管理数据呢?
这个是肯定的!后续会给到答案。
先来看看ViewModel的源码,为什么说到ViewModel创建不建议通过new,而是ViewModelProvider的方式。

// ViewModelProvider.java
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
 // 注释 6, 通过ViewModelStore 拥有者的 getDefaultViewModelProviderFactory方法获取工厂对象
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : ViewModelProvider.NewInstanceFactory.getInstance());
    }
    public ViewModelProvider(@NonNull ViewModelStore store, @NonNull ViewModelProvider.Factory factory) {
        //注释7,  保存工厂 Factory和 缓存对象,ViewModelStore
        mFactory = factory;
        mViewModelStore = store;
    }
    public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
        String canonicalName = modelClass.getCanonicalName();,
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
    public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        //注释 9, 从缓存 mViewModelStore中取 ViewModel的对象
        // Key值是 “androidx.lifecycle.ViewModelProvider.DefaultKey” + 类名
        ViewModel viewModel = mViewModelStore.get(key);
        if (modelClass.isInstance(viewModel)) {
            ......
            // 是响应类的对象则直接返回
            return (T) viewModel;
        }
        ......
        ......
        //注释 10, 缓存中没有 ViewModel对象,用工厂创建,并存入缓存
        viewModel = (mFactory).create(modelClass);
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }

从源码可以看出,ViewModel对象是通过工厂模式进行创建的,并且保存了Factory和缓存对象,当我们通过ViewModelProvider(this).get()方法获取ViewModel对象时,会优先通过缓存获取。

在看看注释6处的getDefaultViewModelProviderFactory()方法

   // ComponentActivity.java
    public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
        ......
        if (mDefaultFactory == null) {
            mDefaultFactory = new SavedStateViewModelFactory(
                    //注释 11, 获取了 Application对象,创建SavedStateViewModelFactory对象
                    getApplication(),
                    this,
                    getIntent() != null ? getIntent().getExtras() : null);
        }
        return mDefaultFactory;
    }

    // SavedStateViewModelFactory.java
    public SavedStateViewModelFactory(@NonNull Application application,
                                      @NonNull SavedStateRegistryOwner owner,
                                      @Nullable Bundle defaultArgs) {
        mSavedStateRegistry = owner.getSavedStateRegistry();
        mLifecycle = owner.getLifecycle();
        mDefaultArgs = defaultArgs;
        mApplication = application;
        //注释 12, 创建 AndroidViewModelFactory工厂
        mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
    }
    public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
        ......
       // 注释 13,通过 AndroidViewModelFactory创建 ViewModel对象
        return mFactory.create(modelClass);
        ......
    }
    public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {
        private static ViewModelProvider.AndroidViewModelFactory sInstance;
        @NonNull
        public static ViewModelProvider.AndroidViewModelFactory getInstance(@NonNull Application application) {
            // 注释14, 单例模式创建工厂实例
            if (sInstance == null) {
                sInstance = new ViewModelProvider.AndroidViewModelFactory(application);
            }
            return sInstance;
        }
        private Application mApplication;
        // 传入 Application对象
        public AndroidViewModelFactory(@NonNull Application application) {
            mApplication = application;
        }
        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
                try {
                    //注释 15, 工厂方法设计模式创建 ViewModel对象,持有 Application的引用
                    return modelClass.getConstructor(Application.class).newInstance(mApplication);
                }
                ......
            }
            return super.create(modelClass);
        }
    }

能看出AndroidViewModelFactory这个工厂,用单例模式创建了该工厂对象,然后使用工厂方法设计模式创建了ViewModel对象,ViewModel创建时传入的时Application参数,这里能够知道ViewModel对象最终持有的,并不是Activity的引用,而是Application的引用,也就是说,为什么ViewModel不容易造成内存泄漏的问题了。
到了这里,为什么不推荐使用new 去创建ViewModel也就迎刃而解了。

自定义view中,如果需要使用ViewModel,虽然官方不建议使用new ViewModel的方式,但是我们还是可以取巧,通过这种方式在view当中去使用它。- -!

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 10:57:45  更:2022-07-03 10:58:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 19:32:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码