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 设置数据,其他两个办法用于主线程。咱们在
init
t结构体中用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的根本用法就介绍到这儿,此系列将会持续更新,欢迎大佬们指正。