JetPack -- ViewModel使用与分析

简介

  • 使用Android AAC组件构建自己的应用之后,为了不让自己停留在仅仅是使用的层面,所以从头开始总结一边AAC组件的使用以及注意的要点
  • ViewModel旨在以注重生命周期的方式存储和管理界面相关的数据, ViewModel 类让数据可在发生屏幕旋转等配置更改后继续存在

作用:

  • 将View中的数据模块进行单独的管理,使得Activity和Fragment更加简单,只需要专注于界面本身不需要管理界面复杂的数据
  • 使用ViewModel的意义在于,平时当一个界面create或者destory的时候,我们需要使用onSaveInstanceState()从onCreate()中的捆绑包回复其数据,但是当数据较大且序列化、反序列化较困难的时候,当采用ViewModel时候,数据是不会丢失的
  • 同时针对某些业务中的异步回调,我们可以利用ViewModel处理数据回调来解决这个问题

ViewModel使用

class MyViewModel : ViewModel() {
    public var number : Int = 0
}

class MainActivity : AppCompatActivity() {
    private lateinit var myViewModel: MyViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        // 首次调用onCreate时创建一个ViewModel ,重新创建的活动也会接受第一次创建的MyViewModel的实例,从而保证数据的一致性
        myViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)


        button.setOnClickListener({
            myViewModel.number++
            textView.setText(myViewModel.number.toString())
        })


        button2.setOnClickListener({
            myViewModel.number += 2
            textView.setText(myViewModel.number.toString())
        })


        textView.setText(myViewModel.number.toString())
    }
}
  • 注意
    • 当Activity finish的时候,框架会调用ViewModel的onCleared()方法来清理资源

ViewModel生命周期

  • 在这里插入图片描述
  • ViewModel生命周期是贯穿整个activity生命周期,包括Activity因旋转造成的重创建,直到Activity销毁才会结束

使用ViewModel在Fragment之间共享数据

  • 之前在项目中如果两个fragment需要通信,就会在Activity中将两者绑定在一起,并且fragment之间还需要互相持有对方的引用
  • 使用ViewModel之后两个fragment可以通过ViewModel关联起来实现数据在两个fragment之间的共享
 class SharedViewModel : ViewModel() {
        val selected = MutableLiveData<Item>()
        fun select(item: Item) {
            selected.value = item
        }
    }

    class MasterFragment : Fragment() {
        private lateinit var itemSelector: Selector
        private lateinit var model: SharedViewModel
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            model = activity?.run {
                ViewModelProviders.of(this)[SharedViewModel::class.java]
            } ?: throw Exception("Invalid Activity")
            itemSelector.setOnClickListener { item ->
                // Update the UI
            }
        }
    }


    class DetailFragment : Fragment() {
        private lateinit var model: SharedViewModel
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            model = activity?.run {
                ViewModelProviders.of(this)[SharedViewModel::class.java]
            } ?: throw Exception("Invalid Activity")
            model.selected.observe(this, Observer<Item> { item ->
                // Update the UI
            })
        }
    }
    

如何保证数据不会丢失

首先我们创建ViewModel
ViewModelProviders.of(this).get(MyViewModel::class.java)
of和get方法


public static ViewModelProvider of(@NonNull FragmentActivity activity,
        @Nullable Factory factory) {
    if (factory == null) {
        factory = activity.getDefaultViewModelProviderFactory();
    }
    return new ViewModelProvider(activity.getViewModelStore(), factory);
}


public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {

    // 通过key从viewModelStore中取出viewModel
    ViewModel viewModel = mViewModelStore.get(key);
    
    // 横屏或者重建判断取出的viewmodel和传入的viewmodel的类型是否一致
    if (modelClass.isInstance(viewModel)) {
        if (mFactory instanceof OnRequeryFactory) {
            // 重新查询该ViewModel
            ((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);
    }
        // 初始进入将ViewModel保存在viewmodelstore中
    mViewModelStore.put(key, viewModel);
    return (T) viewModel;
}
  • 注意:
    • 从上面的代码可以分析出,Activity的销毁重建都是从ViewModelStore中获取的ViewModel----获得的是同一个ViewModel,所以它可以保证数据不会丢失
发布了175 篇原创文章 · 获赞 56 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_39424143/article/details/105055379