您现在的位置是:首页 >技术杂谈 >【Jetpack】LiveData网站首页技术杂谈

【Jetpack】LiveData

Client_Block 2023-06-04 16:00:04
简介【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 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 来实现

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。