1、简单使用
class MainActivity : AppCompatActivity() {
companion object {
val liveData = MutableLiveData<String>()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
liveData.value = "你好-test"
}
fun toTest(view: View) {
startActivity(Intent(this, TestActivity::class.java))
}
}
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
MainActivity.liveData.observe(this, Observer {
Toast.makeText(this, it, Toast.LENGTH_LONG).show()
})
}
}
在MainActivity中有一个liveData,在onOncreate()时赋值为“你好-test”,可以点击按钮跳转到TestActivity。在TestActivity中,监听了liveData的数据变化。
1.1 作用
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity/Fragment)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
- LiveData是一个数据持有者,给源数据包装一层
- 源数据使用LiveData包装后,可以被observer观察,数据有更新时observer可感知。
- 但 observer的感知,只发生在(Activity/Fragment)活跃生命周期状态(STARTED、RESUMED)。
LiveData使得数据的更新能以观察者模式被observer感知,且此感知只发生在 LifecycleOwner的活跃生命周期状态。
1.2 特点
- 确保界面符合数据状态,当生命周期状态变化时,LiveData通知Observer,可以在observer中更新界面。观察者可以在生命周期状态更改时刷新界面,而不是在每次数据变化时刷新界面。
- 不会发生内存泄漏,observer会在LifecycleOwner状态变为DESTROYED后自动remove。
- 不会因 Activity 停止而导致崩溃,如果LifecycleOwner生命周期处于非活跃状态,则它不会接收任何 LiveData事件。
- 不需要手动解除观察,开发者不需要在onPause或onDestroy方法中解除对LiveData的观察,因为LiveData能感知生命周期状态变化,所以会自动管理所有这些操作。
- 数据始终保持最新状态,数据更新时 若LifecycleOwner为非活跃状态,那么会在变为活跃时接收最新数据。例如,曾经在后台的 Activity 会在返回前台后,observer立即接收最新的数据。
2、先看看liveData添加监听的过程
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
// 只能在主线程进行
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore 添加监听的owner处于destroy状态不处理
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); //1
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); //2
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//wrapper添加对生命周期变化的监听
owner.getLifecycle().addObserver(wrapper); //3
}
上面代码的第一处注释就是把生命周期的所有者(activity)和我们传递的观察者参数,合并为一个对象LifecycleBoundObserver,也就是生命周期绑定观察者。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
// activity生命周期改变回调
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
···
}
LifecycleBoundObserver继承了ObserverWrapper和实现了LifecycleEventObserver,在生命周期改变的时候也分发值的改变。
第二处注释mObservers是一个LinkedList,他不是线程安全的。观察者和LifecycleBoundObserver分别作为key和value放入mObservers,存在value的话就直接返回。并且同一个observer不能添加不同的owner(activity)
第三处注释就是LifecycleBoundObserver实现对activity生命周期改变的监听。
3、数据改变的分发
在测试代码中,我们先是设置了liveData的值,在TestActivity中才对liveData进行观察。而实际上在打开TestActivity时就会弹出你好-test的Toast
通过添加观察者的过程可以知道,在activity生命周期改变的时候会调用LifecycleBoundObserver的onStateChanged()
//LifecycleBoundObserver
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
如果当前状态处于destroy移除观察者,并把当前是否处于活跃状态传递给activeStateChanged()
//ObserverWrapper#activeStateChanged(boolean newActive)
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this);
}
}
分发值的改变
//LiveData
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {// 生命周期改变的回调
considerNotify(initiator);
initiator = null;
} else {// setValue()的调用
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
通知
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {//1
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
//2
observer.mObserver.onChanged((T) mData);
}
在注释1处,判断livedata中的version是否小于ObserverWrapper中的version。在注释2处通知了observer值的改变。看看setValue()中的操作。
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
setValue时mVersion++并且给mData赋值。在测试代码中是在TestActivity中添加的观察者dispatchingValue(null);没有观察者响应。
这就可以解释为什么,后添加的观察者可以收到上一个的数据变化。是因为在setVaule时version进行了加1,并把设置的数据赋值给了我mData,在添加观察时注册了生命周期的监听,在活跃状态时调用了considerNotify的方法。在其中判断mLastVersion不大于mVersion说明观察还没得到数据变化的回调,或者不是最新的变化。
3、扩展使用
- 自定义LiveData,本身回调方法覆写:onActive()、onInactive()。
- 实现LiveData为单例模式,便于在多个Activity、Fragment之间共享数据。
官方例子:
public class StockLiveData extends LiveData<BigDecimal> {
private static StockLiveData sInstance; //单实例
private StockManager stockManager;
private SimplePriceListener listener = new SimplePriceListener() {
@Override
public void onPriceChanged(BigDecimal price) {
setValue(price);//监听到股价变化 使用setValue(price) 告知所有活跃观察者
}
};
//获取单例
@MainThread
public static StockLiveData get(String symbol) {
if (sInstance == null) {
sInstance = new StockLiveData(symbol);
}
return sInstance;
}
private StockLiveData(String symbol) {
stockManager = new StockManager(symbol);
}
//活跃的观察者(LifecycleOwner)数量从 0 变为 1 时调用
@Override
protected void onActive() {
stockManager.requestPriceUpdates(listener);//开始观察股价更新
}
//活跃的观察者(LifecycleOwner)数量从 1 变为 0 时调用。这不代表没有观察者了,可能是全都不活跃了。可以使用hasObservers()检查是否有观察者。
@Override
protected void onInactive() {
stockManager.removeUpdates(listener);//移除股价更新的观察
}
}
4、高级用法
4.1 数据修改 - Transformations.map
//数据修改
val liveData1 = MutableLiveData<String>()
val map = Transformations.map(
liveData1
) {
it + "zhangsan"
}
map.observe(this) {
}
4.2 数据切换 - Transformations.switchMap
如果想要根据某个值 切换观察不同LiveData数据,则可以使用Transformations.switchMap()方法
//数据切换
val liveData2 = MutableLiveData<String>()
val liveData3 = MutableLiveData<String>()
//切换条件
val liveDataSwitch = MutableLiveData<Boolean>(
val switchMap = Transformations.switchMap(
liveDataSwitch
) { input ->
if (input == true) {
liveData2
} else {
liveData3
}
}
switchMap.observe(this) {
Log.e("livedatademo", it)
}
liveDataSwitch.value = true
liveData2.value = "lisi"
liveData3.value = "王五"
4.3 观察多个数据 - MediatorLiveData
MediatorLiveData 是 LiveData 的子类,允许合并多个 LiveData 源。只要任何原始的 LiveData 源对象发生更改,就会触发 MediatorLiveData 对象的观察者。
//观察多个数据
val mediatorLiveData = MediatorLiveData<String>()
val liveData4 = MutableLiveData<String>()
val liveData5 = MutableLiveData<String>()
mediatorLiveData.addSource(liveData4) {
Log.e("livedatademo", "liveData4:$it")
mediatorLiveData.value = it
}
mediatorLiveData.addSource(liveData5) {
Log.e("livedatademo", "liveData5:$it")
mediatorLiveData.value = it
}
mediatorLiveData.observe(this) {
Log.e("livedatademo", "mediatorLiveData:$it")
}
liveData5.value = "ktx"
5、Transformations原理
map和switchMap的原理差不多,先看看map是如何修改数据的。
@MainThread
public static <X, Y> LiveData<Y> map(
@NonNull LiveData<X> source,
@NonNull final Function<X, Y> mapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(mapFunction.apply(x));
}
});
return result;
}
现时创建了一个MediatorLiveData,MediatorLiveData是MutableLiveData的子类,看看addSource方法
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {
return;
}
if (hasActiveObservers()) {
e.plug();
}
}
如果MediatorLiveData有活跃观察者,就调用plug():
private static class Source<V> implements Observer<V> {
final LiveData<V> mLiveData;
final Observer<? super V> mObserver;
int mVersion = START_VERSION;
Source(LiveData<V> liveData, final Observer<? super V> observer) {
mLiveData = liveData;
mObserver = observer;
}
void plug() {
mLiveData.observeForever(this);
}
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
}
}
}
Source是MediatorLiveData的内部类,是对源LiveData的包装。plug()中让源LiveData调用observeForever方法添加观察者观察自己。 这里为啥使用observeForever方法呢,这是因为源LiveData在外部使用时不会调用observer方法添加观察者,这里永远观察是为了在源LiveData数据变化时及时回调到 mObserver.onChanged(v)方法,也就是Transformations map方法中的nChanged方法。 而在e.plug()前是有判断 MediatorLiveData 确认有活跃观察者的。
最后map方法中的nChanged方法中有调用MediatorLiveData实例的setValue(mapFunction.apply(x)); 并返回实例。而mapFunction.apply()就是map方法传入的修改逻辑Function实例。