> 文章列表 > 【Jetpack】LiveData

【Jetpack】LiveData

【Jetpack】LiveData

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 artifactprivate 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 来实现