Jetpack明星组件 —ViewModel 这些知识点你必须知道!

本文详细探讨了Jetpack组件中的ViewModel,重点解析其与Activity和Fragment的绑定过程,以及在配置改变时如何保持存活。文章揭示了ViewModel在Activity和Fragment中的创建、恢复原理,以及如何在Fragment间共享数据。通过对Factory接口、ViewModelStore和FragmentManager的讲解,帮助读者深入了解ViewModel的工作机制。

前言

ViewModel 作为 Jetpack 中的明星组件,相信大家都对其有一定的了解。在 Google 的官方介绍中也详细的罗列了 ViewModel 的优点,如:

  1. 可以提供和管理UI界面数据。(将加载数据与数据恢复从 Activity or Fragment中解耦)
  2. 可感知生命周期的组件。
  3. 不会因配置改变而销毁。
  4. 可以配合 LiveData 使用。
  5. 多个 Fragment 可以共享同一 ViewModel。
  6. 等等等…

你也可以通过下列两个视频,更为详细的了解 ViewModel:

在本篇文章中,不会讲解 ViewModel 的使用方式及使用 ViewModel 的原因,而是着重于讲解 ViewModel 的原理。通过阅读本篇文章你能了解到:

  • ViewModel 在 Activity 中的绑定过程。
  • ViewModel 在 Activity 中不会因配置改变而销毁的原理。
  • ViewModel 在 Fragment 中的绑定过程。
  • ViewModel 在 Fragment 中不会因配置改变而销毁的原理。
  • ViewMode 能在 Fragment 中共享的原理。

希望通过该篇文章,大家能对 ViewModel 有更深入的了解。

作者:AndyJennifer
链接:https://www.jianshu.com/p/39ef3e0a5829

ViewModel 与 Activity 的绑定过程

一般情况下使用 ViewModel,我们一般会先声明自己的 ViewModel,并在 Activity 中的 onCreate 方法中使用 ViewModelProviders 来创建 ViewModel。 如下代码所示:

 MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);

在谷歌的最新代码中,不推荐使用 ViweModelProviders(注意是有s的呦) ,而是直接使用 ViewModelProvider 的构造函数来创建 ViewModelProvider 对象。

通过使用 ViewModelProviders 类的 of() 方法,我们会得到一个 ViewModelProvider 对象。如下代码所示:

   public static ViewModelProvider of(@NonNull FragmentActivity activity) {
        return new ViewModelProvider(activity);
    }

ViewModelProvider 类需要我们传递 ViewModelStoreFactory 对象。其构造函数声明如下:

    //使用ViewModelStoreOwner对象构造函数
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
    }

    //使用ViewModelStoreOwner与Factory对象的构造函数
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
        this(owner.getViewModelStore(), factory);
    }

    //使用ViewModelStore与Factory对象的构造函数
    public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
        mFactory = factory;
        mViewModelStore = store;
    }

在 ViewModelProvider 内部,拥有三种类型构造函数:

  • (ViewModelStoreOwner owner):
    • 该构造函数使用 owner 对象的 getViewModelStore() 方法来获取 ViewModelStore 对象,如果传入的 owner 对象也实现了 HasDefaultViewModelProviderFactory 接口时,那么会调用 getDefaultViewModelProviderFactory() 方法获取 Factory。反之,使用内部静态的 NewInstanceFactory 对象来创建 Factory 对象。
  • (ViewModelStoreOwner owner, Factory factory):
    • 该构造函数使用 owner 对象的 getViewModelStore() 方法来获取 ViewModelStore 对象,使用传递的 Factory 对象
  • (ViewModelStore store, Factory factory)
    • 使用 ViewModelStoreFactory 对象的构造函数

Factory 接口介绍

在 ViewModelProvider 中,Factory 主要用于创建 ViewModel,Factory 的声明如下:

    public interface Factory {
        /**
         * 通过给定的Class对象创建ViewModel对象
         * <p>
         *
         * @param modelClass 所需ViewModel的Class对象
         * @param <T>        ViewModel的泛型参数
         * @return 新创建的ViewModel对象
         */
        @NonNull
        <T extends ViewModel> T create(@NonNull Class<T> modelClass);
    }

通过实现 Factory 接口,我们可以实现自己想要的工厂以创建所需的 ViewModel。在 Android 中有多个类都实现了该接口(如 KeyedFactory, AndroidViewModelFactory),这里以默认的 NewInstanceFactory 为例:

    public static class NewInstanceFactory implements Factory {

        private static NewInstanceFactory sInstance;

        @NonNull
        static NewInstanceFactory getInstance() {
            if (sInstance == null) {
                sInstance = new NewInstanceFactory();
            }
            return sInstance;
        }

        @SuppressWarnings("ClassNewInstance")
        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            try {
                //默认使用对应ViewModel类无参的构造函数创建实例对象
                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);
            }
        }
    }

默认情况下, NewInstanceFactory 会调用 ViewModel 的无参构造函数创建实例对象,当然如果你需要在 ViewModel 中使用其他参数,你也可以传递自定义的 Factory。

ViewModelStore 介绍

ViewModelStore 内部维护了一个 HashMap,其 key 为 DEFAULT_KEY + ViewModel的Class对象底层类规范名称,其 value 为对应 ViewModel 对象。每个 Activity 与 Fragment 都对应着一个 ViewModelStore ,用于存储所需的 ViewModel。ViewModelStore 类声明如下所示:

DEFAULT_KEY 值为:“androidx.lifecycle.ViewModelProvider.DefaultKey”

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 (oldVi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值