美文网首页
Jetpack 之 ViewModel 小白入手

Jetpack 之 ViewModel 小白入手

作者: 鹅鹅鹅曲项向天歌呀 | 来源:发表于2021-07-02 19:00 被阅读0次

    声明 : https://www.jianshu.com/p/714062a9af75

    🌸 简介:

      为了能更好的划分职能,Android 为我们提供了 ViewModel 类,专门用于存放应用程序页面所需要的数据.ViewModel 是将页面所需要的数据从页面中剥离出来,页面只需要处理用户交互和展示数据.
      ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel类让数据可在发生屏幕旋转等配置更改后继续存在.

    🌸 生命周期:

    来自官网:


    image.png

       屏幕旋转锁导致 Activity 重建,并不会影响 ViewModel 的声明周期

    🌸 原理:

       看原理之前呢,先看看下面的使用方法哈~~~
       在页面中通过 ViewModelProvider 来实例化一个 ViewModel. ViewModelProvider 接受一个ViewModelStoreOwner类型的对象作为参数,我们实例化的是传的 this,代指当前的 Activity,这是因为我们的 Activity 集成自 ComponentActivity,而ComponentActivity默认实现了ViewModelStoreOwner接口.

    public class ComponentActivity extends androidx.core.app.ComponentActivity implements
            LifecycleOwner,
            ViewModelStoreOwner,
            HasDefaultViewModelProviderFactory,
            SavedStateRegistryOwner,
            OnBackPressedDispatcherOwner {
    
           ........
    
        @NonNull
        @Override
        public ViewModelStore getViewModelStore() {
            if (getApplication() == null) {
                throw new IllegalStateException("Your activity is not yet attached to the "
                        + "Application instance. You can't request ViewModel before onCreate call.");
            }
            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;
        }
    }
    

       接口里面的方法返回的类型为ViewModelStore,从下面ViewModelStore的源码中可以看出来,ViewModel是以 HashMap 的形式被缓存了起来.ViewModel和界面之间没有直接的链接.他们通过ViewModelProvider进行关联,当页面需要 ViewModel 时,会向ViewModelProvider索要, ViewModelProvider会去 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();
            }
        }
    
         //........
    }
    
    

    ⚠️⚠️⚠️敲黑板⚠️⚠️⚠️
       我们在使用ViewModel的时候,要特别注意.Activity由于配置变化导致的销毁重建不会影响ViewModel,ViewModel是独立于页面的,所以不要向ViewModel中传入任何类型的 Context 或者带有 Context 的引用对象,避免内存泄漏
      除了 Activity 实现了ViewModelStoreOwner接口外,Fragment 也实现了,,也可以正常使用 ViewModel.

    🌸 使用方法

    1,build.gradle 文件
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
    
    2,创建 ViewModel 的类
    class TestModel : ViewModel() {
        var number = 0
        
        //Activty 销毁时,才会被调用
        override fun onCleared() {
            super.onCleared()
        }
    }
    

       ViewModel 是一个抽象类,其中有一个方法 onCleared().当 与 ViewModel 相关的Activity被销毁时,该方法才会被调用.我们可以在这个方法里面执行一些资源释放的相关操作,比如,取消倒计时之类的.但是,由于屏幕旋转二]而导致Activity重新创建,并不会调用这个方法.

    3,在TestActivity中使用
    class TestActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_test)
            var testModel = ViewModelProvider(this).get(TestModel::class.java)
            textView1.text = testModel.number.toString()
            button_send.setOnClickListener(View.OnClickListener {
                testModel.number = testModel.number + 1
                textView1.text = testModel.number.toString()
            })
        }
    }
    

       通过ViewModelProvider 实例化 ViewModel,ViewModelProvider会判断是否存在,若存在,会直接返回,若不存在,则会创建一个 ViewModel.
    好了,看图:

    图有点将就了😨😨

    🌸 ViewModel 和 AndroidViewModel

       ViewModel 不能将任何类型的 Context 或者含有 Context 引用的对象传入 ViewModel,因为会引起内存泄漏,但是AndroidViewModel可以,它集成自 ViewModel,并接收 Applicatoin 作为 Context.它的生命周期是和 Application 一样的,所以不算内存泄漏.

    🌸 ViewModel 和 onSaveInstanceState()

      one:💁 onSaveInstanceState()只能保存少量的,支持序列化的数据,但是 ViewModel 没有这个限制.ViewModel 能保存页面中所有的数据,
      two:💁 ViewModel不支持数据的持久化,当界面被彻底销毁时,ViewModel 中的数据就不存在了,但是onSaveInstanceState支持数据的持久化.
      二者,各有千秋.

    END

    image.png

    相关文章

      网友评论

          本文标题:Jetpack 之 ViewModel 小白入手

          本文链接:https://www.haomeiwen.com/subject/lymjjltx.html