LiveData

1、简单使用

class MainActivity : AppCompatActivity() {

    companion object {
        val liveData = MutableLiveData()
    }

    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 仅更新处于活跃生命周期状态的应用组件观察者。

  1. LiveData是一个数据持有者,给源数据包装一层
  2. 源数据使用LiveData包装后,可以被observer观察,数据有更新时observer可感知。
  3. 但 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 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 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生命周期改变的监听。

添加观察者时序图:
liveData添加观察者.png

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, 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说明观察还没得到数据变化的回调,或者不是最新的变化。


通知数据变化时序图.png

liveData类图
LiveData类图.png

3、扩展使用

  1. 自定义LiveData,本身回调方法覆写:onActive()、onInactive()。
  2. 实现LiveData为单例模式,便于在多个Activity、Fragment之间共享数据。

官方例子:

public class StockLiveData extends LiveData {
        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()
    val map = Transformations.map(
        liveData1
    ) {
        it + "zhangsan"
    }
    map.observe(this) {
    }

4.2 数据切换 - Transformations.switchMap

如果想要根据某个值 切换观察不同LiveData数据,则可以使用Transformations.switchMap()方法

    //数据切换
    val liveData2 = MutableLiveData()
    val liveData3 = MutableLiveData()
    //切换条件
    val liveDataSwitch = MutableLiveData(
    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 = "王五"
Transactions.map.png

4.3 观察多个数据 - MediatorLiveData

MediatorLiveData 是 LiveData 的子类,允许合并多个 LiveData 源。只要任何原始的 LiveData 源对象发生更改,就会触发 MediatorLiveData 对象的观察者。

    //观察多个数据
    val mediatorLiveData = MediatorLiveData()
    val liveData4 = MutableLiveData()
    val liveData5 = MutableLiveData()
    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"
MediatorLiveData.png

5、Transformations原理

map和switchMap的原理差不多,先看看map是如何修改数据的。

    @MainThread
    public static  LiveData map(
            @NonNull LiveData source,
            @NonNull final Function mapFunction) {
        final MediatorLiveData result = new MediatorLiveData<>();
        result.addSource(source, new Observer() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
    }

现时创建了一个MediatorLiveData,MediatorLiveData是MutableLiveData的子类,看看addSource方法

    @MainThread
    public  void addSource(@NonNull LiveData source, @NonNull Observer onChanged) {
        Source 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 implements Observer {
        final LiveData mLiveData;
        final Observer mObserver;
        int mVersion = START_VERSION;

        Source(LiveData liveData, final Observer 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实例。

你可能感兴趣的:(LiveData)