• ViewModel的共享(下)


    多个 fragment 如何共享一个 ViewModel

    首先如果我们想要多个不同的 fragment 中拿到同一份的 ViewModel 我们比较常规的用法如下:
    ViewModelProviders.of(this@activity).get(TempViewModel::class.java)
    如上代码所示,在 fragment 中获取ViewModel传入同一个 Activity,就能拿到同一个对应类型的 ViewModel对象。

    怎么拿 ViewModel?

    @NonNull
    @MainThread
    public static ViewModelProvider of(@NonNull FragmentActivity activity,
            @Nullable Factory factory) {
        Application application = checkApplication(activity);
        if (factory == null) {
            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        }
        return new ViewModelProvider(activity.getViewModelStore(), factory);
    }
    
    public <T extends ViewModel> T get(@NonNull 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);
    }
    
    @NonNull
    @MainThread
    public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);
    
        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
        } else {
            viewModel = mFactory.create(modelClass);
        }
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    首先通过静态的 of() 方法我们可以看到,实际上创建的时候传入的一个 ViewModelStore、 factory 创建出 ViewModelProvider。 然后调用 get()方法来获取对应类型的 ViewModel。
    在 get()方法中,会根据传入的 key(可以自定义)去判断 ViewModelStore 中是否有已经创建的 ViewModel,有的话直接返回,没有的话,会根据前面传入的(默认创建的或是传进来) factory 去创建指定ViewModel,然后存到这个 ViewModelStore中,并且返回 ViewModel。

    1. ViewModelStore是啥?
    2. factory 做了什么工作?
    3. 为什么能拿到同一个 ViewModel?

    ViewModelStore是啥?

    ViewModelStore 是什么?简单的理解,那就是用于存储 ViewModel,原理也很简单,内部维护一个 HashMap,我们每次通过 get()方法来获取ViewModel 时,都会到这个 hashmap 中去寻找,是否有对应的实例。

    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 (oldViewModel != null) {
                oldViewModel.onCleared();
            }
        }
    
        final ViewModel get(String key) {
            return mMap.get(key);
        }
    
        Set<String> keys() {
            return new HashSet<>(mMap.keySet());
        }
    
        /**
         *  Clears internal storage and notifies ViewModels that they are no longer used.
         */
        public final void clear() {
            for (ViewModel vm : mMap.values()) {
                vm.clear();
            }
            mMap.clear();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    为什么能拿到同一个ViewModel?

    通过上面代码我们就可以看到,只要传入的 ViewModelStore 相同,对应的 key 相同,我们就可以拿到同一个。

    如何跨 Activity共享ViewModel

    所以通过上面的知识,我们可以知道,只要多个 activity 在获取 ViewModel 时传入同一个 ViewModelStore、同一个 ViewModel Class就可以从对应的 ViewModelStore 中获取到同一份ViewModel了。这样一来就可以实现在跨不同生命周期对象来共享同一份ViewModel。但是需要注意的是,需要考虑传入的 ViewModelStore 的生命周期。

    除此之外,我们还可以通过传入不同的Key,来获取不同实例的同类型ViewModel,具体可阅读ViewModel源码,已经有现成的API提供给我们使用。

  • 相关阅读:
    【动态规划】64. 最小路径和
    HttpServletRequest详解
    linux内核模块符号导出
    【Linux】ASCII码表-256个
    【Designing ML Systems】第 2 章 :机器学习系统设计简介
    计算机毕业设计Java校园绿化管理系统(源码+系统+mysql数据库+Lw文档)
    蓝桥杯刷题--python-20-多路归并,贡献法
    软件开发详解:同城O2O与外卖跑腿系统源码的架构与开发要点
    Python+Appium实现自动化测试
    月薪2w的前端工程师,必盘的实战项目
  • 原文地址:https://blog.csdn.net/coding_sleep/article/details/126091582