• framework通信机制—LiveData使用方法及原理


    LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

    使用 LiveData 的优势

    使用 LiveData 具有以下优势:

    • 确保界面符合数据状态LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知Observer对象。您可以整合代码以在这些Observer对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。
    • 不会发生内存泄漏观察者会绑定到Lifecycle对象,并在其关联的生命周期遭到销毁后进行自我清理。
    • 不会因 Activity 停止而导致崩溃如果观察者的生命周期处于非活跃状态(如返回堆栈中的 activity),它便不会接收任何 LiveData 事件。
    • 不再需要手动处理生命周期界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
    • 数据始终保持最新状态如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
    • 适当的配置更改如果由于配置更改(如设备旋转)而重新创建了 activity 或 fragment,它会立即接收最新的可用数据。
    • 共享资源您可以使用单例模式扩展LiveData对象以封装系统服务,以便在应用中共享它们。LiveData对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察LiveData对象。如需了解详情,请参阅扩展 LiveData

    LiveData的几种用法

    声明一个LiveData

    我们发现LiveData是一个抽象类,它的默认实现子类是MutableLiveData,但是看源码他们没有区别~唯一区别就是set和post方法公开了,之所以这么设计,是考虑到单一开闭原则,只有拿到 MutableLiveData 对象才可以发送消息,LiveData 对象只能接收消息,避免拿到 LiveData 对象时既能发消息也能收消息的混乱使用。

    //1.声明一个MutableLiveData
    val data = MutableLiveData("Test")
    
    
    fun main(){
        //2.监听数据源变化
        data.observe(this){ data->
            //...do somethig
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    组合多个LiveData统一观察

    当我们有多个LiveData时候,某些场景下我们想统一监听,那这个时候我们可以使用MediatorLiveData来对多个LiveData进行统一监听。

    //创建两个长得差不多的LiveData对象
    LiveData liveData1 =  new MutableLiveData();
    LiveData liveData2 = new MutableLiveData();
    
    
     //再创建一个聚合类MediatorLiveData
     MediatorLiveData liveDataMerger = new MediatorLiveData<>();
     //分别把上面创建LiveData 添加进来。
    liveDataMerger.addSource(liveData1, observer);
    liveDataMerger.addSource(liveData2, observer);
    
    
    Observer observer = new Observer() {
      @Override
     public void onChanged(@Nullable Integer s) {
          titleTextView.setText(s);
     }
    //一旦liveData或liveData发送了新的数据 ,observer便能观察的到,以便  统一处理更新UI
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    转换数据

    比如我们希望对一个Int值的LiveData在监听里变成String,那么我们可以用到Transformations.map 操作符进行该操作

    MutableLiveData data = new MutableLiveData<>();
    
    
    //数据转换
    LiveData transformData = Transformations.map(data, input ->   String.valueOf(input));
    //使用转换后生成的transformData去观察数据
    transformData.observe( this, output -> {
    
    
    });
    
    
    //使用原始的livedata发送数据
    data.setValue(10);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    LiveData实现原理

    观察者生命周期

    observe方法负责建立生命周期绑定关系,并注册观察者,如下所示:

    
    
        @MainThread
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
            assertMainThread("observe");
            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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    LiveData将Observer对象加入mObservers中,数据变更时会遍历这个Map分发最新数据。LifecycleBoundObserver类负责监听应用组件的生命周期变化,如下所示:

    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
            @NonNull
            final LifecycleOwner mOwner;
    
    
            LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
                super(observer);
                mOwner = owner;
            }
    
    
            @Override
            boolean shouldBeActive() {
                return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
            }
    
    
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
                if (currentState == DESTROYED) {
                    removeObserver(mObserver);
                    return;
                }
                Lifecycle.State prevState = null;
                while (prevState != currentState) {
                    prevState = currentState;
                    activeStateChanged(shouldBeActive());
                    currentState = mOwner.getLifecycle().getCurrentState();
                }
            }
    
    
            @Override
            boolean isAttachedTo(LifecycleOwner owner) {
                return mOwner == owner;
            }
    
    
            @Override
            void detachObserver() {
                mOwner.getLifecycle().removeObserver(this);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    如onStateChanged方法所示,Lifecycle.State为DESTROYED时,移除观察者,其他情况则更改观察者的状态。

    数据分发

    有两个方法触发数据分发,一个是setValue,在数据变更时触发;一个是ObserverWrapper的activeStateChanged方法,在生命周期变更是触发(例如,从后台切换到前台),就是这个方法确保了应用组件的数据始终是最新的。如下所示:

    
    
        private abstract class ObserverWrapper {
            final Observer mObserver;
            boolean mActive;
            int mLastVersion = START_VERSION;
    
    
            ObserverWrapper(Observer observer) {
                mObserver = observer;
            }
    
    
            void activeStateChanged(boolean newActive) {
                if (newActive == mActive) {
                    return;
                }
                // immediately set active state, so we'd never dispatch anything to inactive
                // owner
                mActive = newActive;
                changeActiveCounter(mActive ? 1 : -1);
                if (mActive) {
                    dispatchingValue(this);
                }
            }
        }
    
    
       @MainThread
        protected void setValue(T value) {
            assertMainThread("setValue");
            mVersion++;
            mData = value;
            dispatchingValue(null);
        }
    
    
        @SuppressWarnings("WeakerAccess") /* synthetic access */
        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, ObserverWrapper>> iterator =
                            mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                        considerNotify(iterator.next().getValue());
                        if (mDispatchInvalidated) {
                            break;
                        }
                    }
                }
            } while (mDispatchInvalidated);
            mDispatchingValue = false;
        }
    
    
        @SuppressWarnings("unchecked")
        private void considerNotify(ObserverWrapper observer) {
            if (!observer.mActive) {
                return;
            }
            // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
            //
            // we still first check observer.active to keep it as the entrance for events. So even if
            // the observer moved to an active state, if we've not received that event, we better not
            // notify for a more predictable notification order.
            if (!observer.shouldBeActive()) {
                observer.activeStateChanged(false);
                return;
            }
            if (observer.mLastVersion >= mVersion) {
                return;
            }
            observer.mLastVersion = mVersion;
            observer.mObserver.onChanged((T) mData);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    considerNotify方法负责实际的数据分发,如果观察者处于非激活态则不分发数据,否则有最新的数据就会分发到观察者,即调用onChanged((T) mData)方法。

    本文主要讲解framework通信机制中的LiveData的用法以及原理,更多有关framework通信技术可以参考《framework全家桶手册》点击可查看详细内容。

  • 相关阅读:
    华为云Astro的前世今生:用7年时间革新低代码开发观念
    提取多个txt数据并合成excel——例子:与中国建交的国家
    OA会议管理系统
    C - Marbles Gym - 102348C
    LEADTOOLS 入门教程: 使用 AWS Lambda 转换文档 - C# .NET Core
    易基因直播预告|细菌微生物基因表达调控表观研究易基因科技
    html5期末大作业 基于HTML+CSS制作dr钻戒官网5个页面 企业网站制作
    LCHub低代码社区:旧的低代码,腾讯怎么讲出新故事
    CRUD搬砖两三年了,怎么阅读Spring源码?
    外卖项目05---套餐管理业务开发
  • 原文地址:https://blog.csdn.net/2301_76813281/article/details/133865401