Android LiveData和MutableLiveData使用详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android LiveData和MutableLiveData使用详解相关的知识,希望对你有一定的参考价值。
参考技术A 参考链接:https://blog.csdn.net/gdutxiaoxu/article/details/86660760
https://www.cnblogs.com/guanxinjing/p/11544273.html
首先LiveData其实与数据实体类(Plain OrdinaryJava Object)是一样的东西,它负责暂存数据。其次LiveData也是一个观察者模式的数据实体类,它的观察者可以回调数据是否已经更新.
LiveData与MutableLiveData的其实在概念上是一模一样的,唯一几个的区别如下:
继承LiveData并且在泛型里写下你的实体类
postValue(this) 这个方法是用于回调数据更新的方法. 你可以在你需要被观察的数据里添加.
调用 ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) 方法,只不过,需要多传递一个 factory 参数。
我们的做法是:实现 Factory 接口,重写 create 方法,在create 方法里面调用相应的构造函数,返回相应的实例。
MutableLiveData只是作用于变量所以我们直接就可以在ViewModel里实例化它,并且在泛型里标注变量的类型.
我们回过头来再来看一下 ViewModelProvider 的 of 方法,他主要有四个方法,分别是
1,2 方法之间的主要区别是传入 Fragment 或者 FragmentActivity。而我们知道,通过 ViewModel of 方法创建的 ViewModel 实例, 对于同一个 fragment 或者 fragmentActivity 实例,ViewModel 实例是相同的,因而我们可以利用该特点,在 Fragment 中创建 ViewModel 的时候,传入的是 Fragment 所依附的 Activity。因而他们的 ViewModel 实例是相同的,从而可以做到共享数据。
说到全局共享数据,我们想一下我们的应用全景,比如说我的账户数据,这个对于整个 App 来说,肯定是全局共享的。有时候,当我们的数据变化的时候,我们需要通知我们相应的界面,刷新 UI。如果用传统的方式来实现,那么我们一般才采取观察者的方式来实现,这样,当我们需要观察数据的时候,我们需要添加 observer,在界面销毁的时候,我们需要移除 observer。
但是,如果我们用 LiveData 来实现的话,它内部逻辑都帮我们封装好了,我们只需要保证LiveData 是单例的就ok,在需要观察的地方调用 observer 方法即可。也不需要手动移除 observer,不会发生内存泄漏,方便快捷。
postValue的特性如下:
setValue()的特性如下:
返回当前值。 注意,在后台线程上调用此方法并不能保证将接收到最新的值。
移除指定的观察者
如果此LiveData具有活动(Activity或者Fragment在前台,当前屏幕显示)的观察者,则返回true。其实如果这个数据的观察者在最前台就返回true,否则false。
当活动观察者的数量从0变为1时调用。这个回调可以用来知道这个LiveData正在被使用,因此应该保持最新。
当活动观察者的数量从1变为0时调用。即观察者的生命周期状态没有STARTED or RESUMED
如果此LiveData具有观察者,则返回true。
设置此LiveData数据当前activity或者Fragment的观察者,会给此activity或者Fragment在前台时回调数据。
移除当前Activity或者Fragment的全部观察者,在使用了observeForever 时调用,即监听了应用在前台状态时的LiveData值变化
Android LiveData使用
LiveData是一个可观察的数据持有者类。 与常规observable不同,LiveData是生命周期感知的,当生命周期处于STARTED或RESUMED状态,则LiveData会将其视为活动状态,这意味着它尊重其他应用程序组件的生命周期,例如Activity,Fragment或Service。
LiveData具有以下优点:
- UI和数据保持一致:遵循观察者模式,生命周期状态更改时,LiveData会通知Observer对象
- 避免内存泄漏:观察者绑定到Lifecycle对象,并在其相关生命周期被破坏后自行清理
- 不会因stop而崩溃:处于非活动状态,不会接收到LiveData事件,如Activity变为不可见
- 自动感知生命周期:LiveData自动管理在观察时意识到相关的生命周期状态变化。
- 数据始终保持最新:生命周期变为非活动状态再次变为活动状态时接收最新数据。 例如,Activity不可见变为可见时立即接收最新数据
- 解决Configuration changes问题:当屏幕旋转或者回收时,重新创建Activity或Fragment,可以即时收到数据变更
- 共享资源:使用单例扩展LiveData,就可在app中共享它
- gradle配置
def lifecycle_version = "2.0.0"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
- 创建LiveData对象
class TestViewModel : ViewModel() {
private lateinit var userName: MutableLiveData<String>
fun getUserName(): MutableLiveData<String> {
if (!::userName.isInitialized) {
userName = MutableLiveData()
loadUsers()
}
return userName
}
private fun loadUsers() {
userName.value = "test"
}
}
- 观察和变更LiveData对象
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var model = ViewModelProviders.of(this).get(TestViewModel::class.java)
model.getUserName().observe(this, Observer {
txt_test.text = it
})// 观察
btn_test.setOnClickListener {
model.getUserName().value = "test 2"
}// 变更
}
}
在变更数据的使用有两种方式可用,一个是setValue,另外一个是postValue,区别是setValue只能在主线程处理,postValue可以在子线程处理。
- LiveData结合Databinding使用
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
var model = ViewModelProviders.of(this).get(TestViewModel::class.java)
binding.let {
it.data = model
it.setLifecycleOwner(this)
}
btn_test.setOnClickListener {
model.getUserName().value = "test 2"
}
}
}
binding对象需要调用setLifecycleOwner(LifecycleOwner lifecycleOwner)设置lifecycleOwner对象。
- 扩展LiveData
通常LiveData只关心观察者的STARTED或RESUMED状态,下面代码片段扩展了LiveData
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private var mStockManager: StockManager? = null
private val mListener = object : SimplePriceListener() {
fun onPriceChanged(price: BigDecimal) {
value = price
}
}
init {
mStockManager = StockManager(symbol)
}
override fun onActive() {
mStockManager.requestPriceUpdates(mListener)
}
override fun onInactive() {
mStockManager.removeUpdates(mListener)
}
}
实现包括以下重要方法:
- 当?LiveData?对象具有活跃观察者时,会调用?onActive()?方法。这意味着,您需要从此方法开始观察数据更新。
- 当?LiveData?对象没有任何活跃观察者时,会调用?onInactive()?方法。由于没有观察者在监听,因此没有理由与?StockManager?服务保持连接。
- setValue(T)?方法将更新?LiveData?实例的值,并将更改通知给任何活跃观察者。
- 使用扩展LiveData
class TestFragment : Fragment() {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val stockLiveData = StockLiveData("")
stockLiveData.observe(this, Observer {
// update UI
})
}
}
observe()?方法将传递 Fragment(它是?LifecycleOwner?的实例)作为第一个参数。这样做表示此观察者绑定到与所有者关联的?Lifecycle?对象,这意味着:
- 如果?Lifecycle?对象未处于活跃状态,那么即使值发生更改,也不会调用观察者。
- 销毁?Lifecycle?对象后,会自动移除观察者
当然可以在多个 Activity、Fragment 和 Service 之间共享它们,只需要把 StockLiveData类实现为单例。
- 转换 LiveData
LiveData?对象分派给观察者之前对存储在其中的值进行更改,或者您可能需要根据另一个实例的值返回不同的?LiveData?实例。其提供了以下方法进行转换
- Transformations.map()
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
? ? user.name + " " + user.lastName
});
- Transformations.switchMap()
LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
要实现您自己的转换,可以使用?MediatorLiveData?类,该类可以监听其他?LiveData?对象并处理它们发出的事件,其可以正确地将其状态传播到源?LiveData?对象。
以上是关于Android LiveData和MutableLiveData使用详解的主要内容,如果未能解决你的问题,请参考以下文章
Android LiveData和MutableLiveData使用详解
Android - ViewModel、LiveData、Room 和 Retrofit 以及协程放在 kotlin 中