栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Jetpack-ViewModel用法与源码分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Jetpack-ViewModel用法与源码分析

目录
  • 前言
  • 一、ViewModel使用
    • 1、定义ViewModel
    • 2、创建ViewModel
  • 二、源码分析
    • 1、创建流程
      • ViewModelStore
      • ViewModelProvider.NewInstanceFactory()
      • get(MyViewModel::class.java)
    • 2、Activity重建
    • 3、ViewModel生命周期

前言

ViewModel组件的作用就是保证数据的稳定性。当我们在某Activity输入100个字段以后,发生横竖屏切换,Activity重建,此时数据会保存在ViewModel中,Activity重建后再从ViewModel取值即可,ViewModel的生命周期很长,数据不会丢失,配合DataBinding、LiveData使用会更方便。

需要注意的是,ViewModel只是Jetpack中的一个组件库,和MVVM中的ViewModel层是两个概念。

一、ViewModel使用 1、定义ViewModel
class MyViewModel : ViewModel() {
    var number : Int = 0
}

如果我们需要使用Application上下文可以继承AndroidViewModel,ViewModel中是不能持有Activity上下文的,因为ViewModel的生命周期比Activity更长,会造成内存泄漏。
我们这里简单定义一个变量number,在Activity中来修改和观测它的值。

2、创建ViewModel
class MainActivity : AppCompatActivity() {

    private lateinit var myViewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        myViewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())
            .get(MyViewModel::class.java)

        text_number.text = "${myViewModel.number}"

        btn_plus.setOnClickListener {
            text_number.text = "${++myViewModel.number}"
        }
    }
}

点击按钮修改ViewModel中number变量的值,横竖屏切换后,Activity重建,number值没变。这样,不需要添加任何保存的代码就保证了数据的稳定。

二、源码分析 1、创建流程 ViewModelStore

新版本的ViewModel使用ViewModelProvider来创建ViewModel,第一个参数是环境,ComponentActivity实现了ViewModelStoreOwner接口,这里第一个参数实际传入的就是ViewModelStoreOwner,包含getViewModelStore()方法返回一个ViewModelStore。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {
        ...
 }   
public interface ViewModelStoreOwner {
    
    @NonNull
    ViewModelStore getViewModelStore();
}

ViewModelStore源码也非常简单,只是一个单纯的存储类,提供了get、put、clear等方法

public class ViewModelStore {

    private final HashMap 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 keys() {
        return new HashSet<>(mMap.keySet());
    }

    
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}
ViewModelProvider.NewInstanceFactory()

工厂模式,依赖倒置原则,通过反射来实例化传入的自定义ViewModel类

    public static class NewInstanceFactory implements Factory {
        public  T create(@NonNull Class modelClass) {
            try {
                return modelClass.newInstance();
            } catch (InstantiationException e) {
                ...
            }
        }
    }
get(MyViewModel::class.java)

查看ViewModelStore有没有此ViewModel,如果有,直接返回,没有则通过工厂来创建并保存入ViewModelStore。

    public  T get(@NonNull String key, @NonNull Class modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);
        if (modelClass.isInstance(viewModel)) {
            //noinspection unchecked
            return (T) viewModel;
        } else {
            ...
        }
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
        } else {
            viewModel = (mFactory).create(modelClass);
        }
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }
2、Activity重建

通过查看ComponentActivity源码,当Activity重建后,会执行onRetainNonConfigurationInstance方法,AMS保存的数据,当mViewModelStore为空时,可以从NonConfigurationInstances中重新拿到mViewModelStore,当mViewModelStore不为空,getViewModelStore方法就会返回当前的mViewModelStore用于数据的恢复

    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;
    }
    public ViewModelStore getViewModelStore() {
        ...
        if (mViewModelStore == null) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
    }
3、ViewModel生命周期

网上有一张很经典的图,是说ViewModel的生命周期很长,比Activity的生命周期要长

其实,关于ViewModel的生命周期可以从ComponentActivity的构造方法中看到这样一段代码

        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    if (!isChangingConfigurations()) {
                        getViewModelStore().clear();
                    }
                }
            }
        });

只有Activity在ON_DESTROY状态,并且通过这个判断isChangingConfigurations,是真正的被销毁了之后,mViewModelStore才会被清空。这里的状态又用到了Lifecycle的状态,可以看到Lifecycle在整个Jetpack组件当中的重要地位,关于Lifecycle状态和事件之间的关系,在我上一篇文章中有介绍。
到此,ViewModel组件的主线流程就看完了,核心就是mViewModelStore存储以及nc恢复,同时通过Lifecycle来控制销毁。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/584792.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号