Android Jetpack - LiveData
Posted teletian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Jetpack - LiveData相关的知识,希望对你有一定的参考价值。
◾︎简介
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
这是官网上的一段话。意思就是 LiveData 的更新能够被 LifecycleOwner 所感知,但是前提是 LifecycleOwner 处于活跃状态。这样就有效的避免了更新 UI 时 Activity 已经不处于活跃而导致的崩溃。
本文代码使用 Kotlin 讲解,若需查看 Java 代码写法,请参考文末 Sample
◾︎添加依赖
LiveData 一般和 ViewModel 一起使用。
def lifecycle_version = "2.3.1"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
◾︎使用
应当避免将 LiveData 直接存储在 Activity / Fragment 中,因为 Activity / Fragment 只负责 UI 显示,而不负责数据存储。
简单的使用 LiveData
- 在 ViewModel 中定义 LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class NameViewModel : ViewModel() {
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
}
- 使用 LiveData 的 observe 方法
import androidx.lifecycle.ViewModelProvider
viewModel = ViewModelProvider(this)[NameViewModel::class.java]
viewModel?.currentName?.observe(this, { name -> textView.text = name })
observe 方法有两个参数
- 第一个是 LifecycleOwner 对象。这样 LiveData 就会感知 LifecycleOwner 的生命周期,只在 LifecycleOwner 活跃的时候才去调用第二个参数的 onChanged 方法
- 第二个参数是 Observer 对象。Observer 是一个 interface,它的 onChanged 会在 LiveData 更新的时候被调用
- 更新 LiveData
viewModel?.currentName?.value = "更新 LiveData"
更新 LiveData 有两种方法
- setValue。在主线程时使用 setValue
- postValue。在子线程时使用 postValue,其实内部就是使用了 Handler 把值 post 到主线程去了。如果在主线程执行之前调用了多次 postValue,只有最后一次有效
LiveData vs MutableLiveData
LiveData 的 setValue 和 postValue 是 protected 的,只能在 ViewModel 内部使用。MutableLiveData 的 setValue 和 postValue 是 public 的,可以在任何地方使用。
自定义 LiveData
自定义一个监听网络状态的 LiveData
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.util.Log
import androidx.annotation.MainThread
import androidx.lifecycle.LiveData
class NetworkLiveData(private val context: Context?) : LiveData<NetworkInfo?>() {
private var networkReceiver: NetworkReceiver
private var intentFilter: IntentFilter
init {
networkReceiver = NetworkReceiver()
intentFilter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
}
companion object {
private lateinit var instance: NetworkLiveData
@MainThread
fun getInstance(context: Context?): NetworkLiveData {
instance = if (::instance.isInitialized) instance else NetworkLiveData(context)
return instance
}
}
override fun onActive() {
super.onActive()
Log.d("tianjf", "onActive")
context!!.applicationContext.registerReceiver(networkReceiver, intentFilter)
}
override fun onInactive() {
super.onInactive()
Log.d("tianjf", "onInactive")
context!!.applicationContext.unregisterReceiver(networkReceiver)
}
inner class NetworkReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val connectivityManager =
context?.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
val networkInfo = connectivityManager?.activeNetworkInfo
getInstance(context).value = networkInfo
}
}
}
自定义 LiveData 会覆写 onActive 和 onInactive 方法。它们会监听 LifecyclerOwner 的生命周期。当进入活跃状态(STARTED 或者 RESUMED)时,调用 onActive 方法,当进入非活跃状态时,调用 onInactive 方法。
在 onActivie 中注册广播,在 onInactive 中注销广播。这样代码就非常清晰明了了,网络状态的处理和 Activity/Fragment 分离开了。
转换 LiveData
转换会用到 Translations.map 和 Translations.switchMap
map、switchMap 和 RxJava 中的 map、flatMap 类似
Translations.map
val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = Transformations.map(userLiveData) {
user -> "${user.name} ${user.lastName}"
}
当更新 userLiveData 的值时,会自动触发 userName 的 setValue 操作。其实就是对数据做 map 操作,转换为需要的格式。
Translations.switchMap
private fun getUser(id: String): LiveData<User> {
...
}
val userId: LiveData<String> = ...
val user = Transformations.switchMap(userId) { id -> getUser(id) }
当设置 userId 的时候,会自动触发 getUser 操作并返回另一个 LiveData
MediatorLiveData
map 和 switchMap 的源码中都使用到了 MediatorLiveData。
从名称可以看出,MediatorLiveData 使用了终结者模式。
MediatorLiveData 可以接管普通的 LiveData,使得当 LiveData 有数据更新的时候,MediatorLiveData 也能够 “收到响应”。
private val originData = MutableLiveData<String>()
private val mediatorLiveData = MediatorLiveData<String>()
mediatorLiveData.addSource(originData) { Log.i("tianjf", "originData: $it") }
MediatorLiveData 可以添加多个 LiveData
private val originData1 = MutableLiveData<String>()
private val originData2 = MutableLiveData<String>()
private val mediatorLiveData = MediatorLiveData<String>()
mediatorLiveData.addSource(originData1) { mediatorLiveData.value = "originData: $it" }
mediatorLiveData.addSource(originData2) { mediatorLiveData.value = "originData: $it" }
observe 和 observeForever
observeForever 和 observe 的区别是,LifecyclerOwner 在非活跃状态下也会调用 Observer 的 onChanged 方法。
为了防止内存泄露,必须手动调用 removeObserver 方法
◾︎Sample
以上是关于Android Jetpack - LiveData的主要内容,如果未能解决你的问题,请参考以下文章
Android Jetpack架构组件带你了解Android Jetpack
Android Jetpack架构组件——什么是Jetpack?
Android Jetpack架构组件——什么是Jetpack?