LiveData
什么是 LiveData
LiveData 是一个具有生命周期感知能力的可被观察的数据持有类,且只有在 Lifecycle 激活状态下才会通知观察者。
为什么需要 LiveData
在 如何写个高质量的 Android App? 中,提到 避免不必要的数据更新
只有在 Lifecycle 激活状态下才会通知观察者,且如果非激活状态产生数据变更,在返回激活状态时会自动通知观察者。
激活状态是指
STARTED
RESUMED
因为是生命周期感知的,所以在 Activity 销毁的时候,数据也会自动清除,这样就不会内存泄漏来,也不需要在 onDestory 的时候各种
xx = null
了。
这一切都是 LiveData 已经提供好的功能,你的使用非常简单。
怎么使用 LiveData
直接使用 LiveData
通过继承 自定义 LiveData
LiveData 之间的转换
导入库
因为 LiveData 也属于生命周期组件的一部分,所以同样的引入 Support Library
26.1 以上的版本就行。
LiveData
LiveData 是一个抽象类,其实通常是使用它其中的一个子类,MutableLiveData
class MainActivity : AppCompatActivity() {
lateinit var userData: MutableLiveData<User>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 1. 初始化
userData = MutableLiveData()
// 2. 观察,通过生命周期观察,只有在活动状态下才会接收到通知
userData.observe(this, Observer { user ->
// 修改 UI
username?.text = user?.name
})
// 2. 观察,非生命周期观察,只要数据变化就会收到通知
// userData.observeForever(Observer { user ->
// // 修改 UI
// username?.text = user?.name
// })
// 3. 修改值
userData.value = User(0, "Liu") // 主线程修改用 setValue
Thread(Runnable {
Thread.sleep(2000)
userData.postValue(User(1, "Gavin")) // 异步修改用 postValue
}).start()
}
}
LiveData 很贴心的提供了两种观察:
生命周期感知的
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
只有在活动状态下才会接收到通知
非生命周期感知
public void observeForever(@NonNull Observer<T> observer)
只要数据变化就会收到通知
LiveData 其实也能很好的用在异步线程中,不仅仅是 postValue
方法可以在异步线程中更新数据,还因为是观察者模式,能够很好的和 Future 多线程模型 相结合,假设需要异步获取一个 Json 数据,网络库可以直接返回一个 LiveData,等网络加载完成后,再更新数据。
自定义 LiveData
class CustomLiveData : MutableLiveData<Int>() {
override fun onActive() {
super.onActive()
registerReceiver()
}
override fun onInactive() {
super.onInactive()
unregisterReceiver()
}
private fun registerReceiver() {
}
private fun unregisterReceiver() {
}
}
onActive()
是在 LiveData 有观察者的时候被触发,这里应该做一些初始化操作;onInactive()
是在 LiveData 没有观察者的时候被触发,这里应该做一个些数据清空的操作;
合并多个 LiveData
有这么个需求,一个资源可能是来源本地缓存或者网络,如何对外只暴露一个对象,就能同时收到本地缓存或者网络的数据?
通过 MediatorLiveData
// 伪代码
val networkUser = MutableLiveData<User>() // 网络
val localCacheUser = MutableLiveData<User>() // 本地缓存
val fullUserData = MediatorLiveData<User>()
fullUserData.addSource(localCacheUser, { fullUserData.value = it })
fullUserData.addSource(networkUser, { fullUserData.value = it })
fullUserData.observe(this, Observer {
username2?.text = it?.name
})
// 异步获取
Thread(Runnable {
localCacheUser.postValue(User(2, "User Local")) // 本地缓存先拿到
Thread.sleep(2000)
networkUser.postValue(User(2, "User NetWork")) // 网络数据拿到
}).start()
转换 LiveData
有时候可能需要把一个 LiveData 转换成另外一个 LiveData,那么就需要用到 LiveData 的转换功能
Transformations.map()
针对直接返回某个数据,用这个
// MainActivity.kt
teamNameData = Transformations.map(userData) { "${it.name} - Team" }
teamNameData.observe(this, Observer {
team?.text = it
})
Transformations.switchMap()
针对返回另外一个 LiveData ,用这个
// MainActivity.kt
teamNameData = Transformations.map(userData) { "${it.name} - Team" }
teamNameData.observe(this, Observer {
MutableLiveData<String>()
})
Transformations API,是可以实现,源数据变化后跟着变化,比如上面的例子,如果 userData
变了,会自动触发 teamNameData
变化。
LiveData 实现原理
类图
源码解析
1. LiveData 如何实现对生命周期感知的?
在添加观察者的时候需要传入 LifecycleOwner
,然后 addObserver()
,所以就实现了生命周期感知。同时在 LifecycleOwner
被销毁的时候,会自动清除数据。
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
// 生命周期监听
owner.getLifecycle().addObserver(wrapper);
}
// DESTROYED 时清除数据
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
...
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
...
}
2. LiveData 如何实现数据变化通知的?
// 1 修改数据, postValue 最终也是调用 setValue
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
// 2 迭代通知
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
// 3 通知
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
3. Transformations API 是如何实现的?
通过 MediatorLiveData 实现
map
public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source,
@NonNull final Function<X, Y> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(func.apply(x));
}
});
return result;
}
switchMap
public static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> trigger, @NonNull final Function<X, LiveData<Y>> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(trigger, new Observer<X>() {
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x) {
LiveData<Y> newLiveData = func.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
result.addSource(mSource, new Observer<Y>() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
总结
LiveData 是不是也很简单?
除了对基本的 LiveData 操作需要了解之外,从 Transformations API 的实现就是基于 MediatorLiveData,就能知道其强大之处,原理却非常简单,所以你应该学会 MediatorLiveData
的用法。