Livedata是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。本文结合源码介绍其实现原理。
使用示例
考虑这个例子:在viewmodel类里面创建了一个livedat,在Activity在监听livedata,实例代码如下
- 在 ViewModel 中创建 LiveData 对象
/// viewmodel类
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class UserViewModel : ViewModel() {
private val _user = MutableLiveData<User>()
val user: LiveData<User> get() = _user
fun fetchUser() {
// 模拟从 Model 层获取数据
_user.value = User("John Doe", 30)
}
}
- 观察 LiveData
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
class MainActivity : AppCompatActivity() {
private val userViewModel: UserViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 观察 LiveData 对象
userViewModel.user.observe(this, Observer { user ->
// 更新 UI
findViewById<TextView>(R.id.userName).text = user.name
findViewById<TextView>(R.id.userAge).text = user.age.toString()
})
// 获取用户数据
userViewModel.fetchUser()
}
}
如何实现生命周期感知
- 当调用 observe 方法时注册监听的时候,LiveData 会创建一个 LifecycleBoundObserver 实例,并将其添加到 LifecycleOwner(即例子中的Activity) 的生命周期观察者列表中,这样当Activity的生命周期发生变化就会通知livedata。 在onStart, onResume的时候把当前注册的observer设置为活跃状态,当onPause和onStop的时候把当前注册的observer设置为不活跃状态, 当onDestroy的时候把当前的observer移除掉,以此避免activity泄漏。
下面看看observe方法的实现
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// mObservers是该livedata的观察者列表
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
// 这里监听组件的生命周期(在本文例子中对应activity),在LifecycleBoundObserver类中会处理各种生命周期回调
owner.getLifecycle().addObserver(wrapper);
}
//LifecycleBoundObserver类中会处理各种生命周期回调
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
// 当onDestroy的时候把当前的observer移除掉
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
// 这里有个循环是因为有可能在执行循环体的时候生命周期发生了变化
while (prevState != currentState) {
prevState = currentState;
// 这里在onStart, onResume的时候把当前注册的observer设置为活跃状态,当onPause和onStop的时候把当前注册的observer设置为不活跃状态
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
- 当liveddata的数据变化的时候,通知所有处于活跃状态的observer
看看更新数据的方法
protected void setValue(T value) {
// 这里检查了是否主线程,避免在子线程操作UI
assertMainThread("setValue");
mVersion++;
mData = value;
// 这里最终会调用到considerNotify方法
dispatchingValue(null);
}
private void considerNotify(ObserverWrapper observer) {
// 如果不活跃,直接返回
if (!observer.mActive) {
return;
}
// 执行观察者的回调
observer.mObserver.onChanged((T) mData);
}
总结
至此,我们了解了livedata如何感知生命周期,并且livedata也通过检查线程规避了在子线程更新UI的问题。