Jetpack从入门到简直入门(二)

我正在参加「启航计划」

前语

Jetpack系列:

Jetpack从入门到简直入门(一) – ()

Jetpack从入门到简直入门(二) – ()

Jetpack从入门到简直入门(三) – ()

本文是我在学习guolin大神的《榜首行代码》第三版Jetpack部分的知识总结,文中部分代码参阅自《榜首行代码》第三版

在阅览本文前,您需求把握kotlin语言的根本语法,了解ViewModel的应用

LiveData

简介

在学习LiveData之前,我接触到呼应式编程是在学习RxJava的时候。RxJava的观察者形式确实给开发带来了很大的便当,但是RxJava的一些库学习起来过于复杂,对初学者有不小的挑战。就在此时,Jetpack 提供的,专用于Android的呼应式编程组件LiveData横空出世。它和它的绝佳拍档ViewModel一同,再次提高了程序员的开发速度。接下来就让咱们一同学习LiveData并探究LiveData与ViewModel的配合使用。

LiveData 的根本用法

咱们先写一个带ViewModel的简易的计数器程序,此计数器能做到数据耐久化。具体请参阅Jetpack从入门到简直入门(一) – ()

  • MainViewModel

    class MainViewModel(countReserved: Int) : ViewModel() {
      var counter = countReserved
    }
    
  • MainActivity

    class MainActivity : AppCompatActivity() {
      lateinit var viewModel: MainViewModel
      lateinit var sp: SharedPreferences
      val binding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) }
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    ​
        setContentView(binding.root)
        sp = getPreferences(Context.MODE_PRIVATE)
        val countReserved = sp.getInt("count_reserved", 0)
        viewModel = ViewModelProvider(this, MainViewModelFactory(countReserved)).get(MainViewModel::class.java)
        binding.plusOneBtn.setOnClickListener {
          viewModel.counter++
          refreshCounter()
         }
        binding.clearBtn.setOnClickListener{
          viewModel.counter = 0;
          refreshCounter()
         }
        refreshCounter()
       }
      private fun refreshCounter() {
        binding.infoText.text = viewModel.counter.toString()
       }
    ​
      override fun onPause() {
        super.onPause()
        sp.edit {
          putInt("count_reserved", viewModel.counter)
         }
       }
    ​
    }
    

    尽管咱们能够实现每按一次按钮,counter就+1,但咱们都是在Activity中手动获取ViewModel 中的数据,若ViewModel的内部开启了线程去执行耗时操作,那么Activity马上去获取ViewModel 中的数据的话,只能得到改变发生前的数据,也便是原数据。咱们期望的是,ViewModel只要发生变化就能自动告知Activity,所以咱们应该使用LiveData对此程序进行优化。

LiveData的优势

LiveData是呼应式编程组件,当底层数据发生变化时,LiveData 会通知Observer目标,咱们能够在Observer目标中编写更新UI的代码,意思便是,当LiveData发生变化时,UI会收到新数据偏重绘。且与一般的遵循观察者形式的组件不同,LiveData还具有生命周期感知能力

刻不容缓,咱们开始编写具体的代码。

  • MainViewModel

    class MainViewModel(countReserved: Int) : ViewModel() {
      var counter = MutableLiveData<Int>()
      init {
        counter.value = countReserved
       }
    ​
      fun plusOne(){
        val count = counter.value ?: 0 //当获取到的数据为空时,就用0来作为默许计数
        counter.value = count + 1
       }
    ​
      fun clear(){
        counter.value = 0
       }
    }
    

    咱们把本来的counter改成了一个包含Int型的MutableLiveData目标。MutableLiveData是一种可变的LiveData,它有3钟读写数据的办法,分别为getValue()setValue()postValue(),值得注意的是,postValue()办法用于在非主线程中给LiveData 设置数据,其他两个办法用于主线程。

    咱们在initt结构体中用setValue()counter设置数据,在plusOne()clear()中对counter进行修正

  • MainActivity

    class MainActivity : AppCompatActivity() {
       ...
      override fun onCreate(savedInstanceState: Bundle?) {
         ...
        binding.plusOneBtn.setOnClickListener {
          viewModel.plusOne()
         }
        binding.clearBtn.setOnClickListener{
          viewModel.clear()
         }
        //LiveData目标能够调用它的observe()办法观察数据的变化
        viewModel.counter.observe(this, Observer { count ->
          binding.infoText.text = count.toString()
         })
       }
    ​
      override fun onPause() {
        super.onPause()
        sp.edit {
          putInt("count_reserved", viewModel.counter.value ?: 0)
         }
       }
    ​
    }
    

    上述代码中最关键的地方为viewModel.counter中的observe()办法

    observe()办法接收两个参数:

    • 榜首个参数是一个LifecycleOwner目标,Activity 本身便是一个LifecycleOwner目标,这儿咱们直接传this
    • 第二个参数是一个Observer接口,当counter中的数据发生变化时,就会回调到这儿,咱们在这儿更新UI

以上便是LiveData的根本用法,但这个程序还有缺点,咱们把counter这个可变的LiveData 暴露给了外部,破坏了ViewModel 数据的封装性。下面咱们持续改造MainViewModel

class MainViewModel(countReserved: Int) : ViewModel() {
  private val _counter = MutableLiveData<Int>()
  val counter: LiveData<Int>
    get() = _counter //在counter的get办法中回来_counter变量
  init {
    _counter.value = countReserved
   }
​
  fun plusOne(){
    val count = _counter.value ?: 0 //当获取到的数据为空时,就用0来作为默许计数
    _counter.value = count + 1
   }
​
  fun clear(){
    _counter.value = 0
   }
}

咱们将本来的counter变量改名为counter变量,并给它加上private修饰符,使得counter对外部不行见。咱们又界说了不行变的LiveData类型的counter,并在它的get()特点办法中回来counter变量,当外部调用counter变量时,实际上获得的便是counter的实例,但无法给counter设置数据。

好了,关于LiveData的根本用法就介绍到这儿,此系列将会持续更新,欢迎大佬们指正。