1 setValue() 和 postValue() 的区别?
2 liveData 是如何感知生命周期的?
3 连续 postValue() 为什么会丢失数据?
4 livedata 是粘性的么?
5 为什么 livedata 要设计成粘性的?
1.LiveData 是什么?
具有感知生命周期的可观察的数据存储器类
2.LiveData 使用场景
在 ViewModel 内部使用,数据通过观察者驱动视图的更新,降低 MVVM 门槛。
3.LiveData 优势
感知生命周期
- 遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
- 如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。
确保界面符合数据状态,数据始终保持最新状态 - 保证数据是最新的,LiveData 的目的是为了保证最后一条数据是最新的,所以在数据变更的时候,可能会出现数据丢失的情况也是正常的(连续使用 postValue() 的场景)。毕竟它只保证最后的数据。
- 适当的配置更改也可以保证最新数据。如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。ViewModel的生命周期比较长,会在这种场景下保存下来,切换以后判断 livedata 内部的版本,从而保证最新的数据。
不会发生内存泄露,不会因 Activity 停止而导致崩溃,不再需要手动处理生命周期 - livedata 的观察者是绑定了 Lifecycle 对象的,在退出的时候,会自动处理解绑
共享资源 - 您可以使用单例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象。如需了解详情,请参阅扩展 LiveData。
4.基础使用
step1 声明一个 LiveData
class NameViewModel : ViewModel() {
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
}
step2 开始订阅
observe 和 observeForever
class NameActivity : AppCompatActivity() {
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
private val model: NameViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Other code to setup the activity...
// Create the observer which updates the UI.
val nameObserver = Observer<String> { newName ->
// Update the UI, in this case, a TextView.
nameTextView.text = newName
}
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.currentName.observe(this, nameObserver)
model.currentName.observe(this) {
Log.d("TAG", "LiveData: $it")
}
model.currentName.observeForever {
Log.d("TAG", "Forever LiveData: $it")
}
}
}
step3 更新数据
setValue 和 postValue
//主线程调用 setValue()
model.currentName.setValue(anotherName)
//子线程调用 postValue()
model.currentName.postValue(anotherName)
5.注意事项
5.1 setValue() 必须在主线程
java.lang.IllegalStateException: Cannot invoke setValue on a background threadt
5.2 连续调用postValue(),中间数值会被舍弃
需要获取每次值状态的场景需要注意,比如进度条监听等
5.3 LiveData 数据倒灌问题
LiveData 默认是粘性的,可以通过修改 mLastVersion 来实现