Android Jetpack系列02——ViewmodelWithLivedata

上一篇中讲到了viewmodel,当我点击那个自增按钮时,并不能立刻看到数字显示变化。需要我们重新进入界面,因为我把界面刷新写在了onResume()中。那么是否有方法,当我的数据变化时,那些与该数据绑定的UI能立刻自动刷新呢?鉴于这种需要,Livedata就登场了!!!

1、Livedata是什么?

答:Livedata是一种增强型的观察者模式,增强之处在于它能感知到生命周期。当被观察者的数据发生变化,和Livedata绑定的生命周期组件处于活跃状态时,才会被通知,如果处于不活跃状态,那么不会收到数据的通知。

2.使用Livedata能带来什么好处?

答:1、避免处理回调异常情况。开发中,譬如我们需要将指定的网络数据展示到一个界面上,我们一般是异步访问网络,在回调中去更新UI。回调有时候是不可控的,出现的很多情况是,网络回调后,用户已经退出了UI界面,这个时候就不需要再去显示UI,并且很可能因为UI不可见,导致出现一个空指针异常。
2、功能代码更集中。一般情况多处UI都需要关联某个数据,那么使用livedata,就可以使得UI控制更集中,不用到处在更新UI,导致代码维护不可控。
3、链式更新。譬如:有a.b.c三个数据(不限制一定要是数据,也有可能是函数),c依赖b,b依赖a,使用livedata就能做到,当a改变时,b和c也能跟着改变,代码写起来真是非常顺手加简单,看后面的例子时就会有这个感受。

3、怎么使用Livedata?

我们继续使用上篇中的viewmodel例子,只是将Viewmodel中的Int字段替换为了Livedata字段。

  1. 构建Viewmodel
class BlankViewModel : ViewModel() {
    var number = MutableLiveData<Int>()
    //这个map就是我上面说到的链式更新,当number变化时,会自动调用map中的函数,并更新score的返回值
    var score = Transformations.map(number) {
            it?.times(10)
    }
}

2、在Fragment中获取Livedata.
首先是Fragment01,其中有个按钮,点击后呢viewmodel中的number字段自增1。

class BlankFragment01 : Fragment() {
    private lateinit var viewModel: BlankViewModel
    override fun onAttach(context: Context?) {
        super.onAttach(context)
        viewModel = ViewModelProviders.of(activity as FragmentActivity).get(BlankViewModel::class.java)
        viewModel.number.observe(activity as FragmentActivity,object :Observer<Int>{
            override fun onChanged(t: Int?) {
                number_tv_01.setText(viewModel.number.value?.toString())
            }
        })

    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
//        kotlin中可以直接使用布局文件中的控件id来操作该view,但是前提是在onViewCreated中使用。
        increase.setOnClickListener {
        //注意这里的判空,livedata中的值未设置时,value字段是null
            if (viewModel.number.value == null) {
                viewModel.number.value=1
            }else{
                var value = viewModel.number.value
                viewModel.number.value = value?.inc()
            }
        }
    }

接下来是Fragment02,我们对同一个的viewmodel进行观察

class BlankFragment02 : Fragment() {
    private lateinit var viewModel: BlankViewModel
    override fun onAttach(context: Context?) {
        super.onAttach(context)
        viewModel = ViewModelProviders.of(activity as FragmentActivity).get(BlankViewModel::class.java)
        //添加observe方法就能添加观察了,当score livedata数据发生变化时,onChange()回调就会自动执行
        viewModel.score.observe(activity as FragmentActivity,object :Observer<Int?>{
            override fun onChanged(t: Int?) {
                number_tv.text = t?.toString()
            }
        })
    }
    }

效果如下Gif所示,当我点击按钮时,viewmodel中的number自增1,同时每当number变化时,就会调用map中的lambda表达式,并修改score的值,所以number变化,会引起score的链式变化。

var score = Transformations.map(number) {
            it?.times(10)
    }

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/HelloMagina/article/details/84950257