美文网首页
jetapck 学习 LiveData

jetapck 学习 LiveData

作者: 刘景昌 | 来源:发表于2021-03-16 10:01 被阅读0次

    1.介绍
    定义:LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity/Fragment)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
    理解:

    • LiveData 是给源数据包裹了一层结构
    • LiveData 包裹的数据可以被 以被observer观察,数据改变也会被以被observer监听到
    • observer的感知,只发生在 活跃生命周期状态(STARTED、RESUMED)
      LiveData的优势:
    • 不会因为activity的停止崩溃:观察者可以在界面的生命周期 发生改变的时候才刷新数据,而不是每次数据发生变化的时候
    • 不会发送内存泄露,并且不需要手动解除:observer在LifecycleOwner的状态变为DESTROYED
      2.LiveData的基本使用
    • 创建LiveData实例,指定源数据类型
    • 创建Observer实例,实现onChanged()方法,用于接收源数据变化并刷新UI
    • LiveData实例使用observe()方法添加观察者,并传入LifecycleOwner
    • LiveData实例使用setValue()/postValue()更新源数据 (子线程要postValue())
      举个例子测试一下
    public class LiveDataTestActivity extends AppCompatActivity{
    
       private MutableLiveData<String> mLiveData;
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_lifecycle_test);
    
           //liveData基本使用
           mLiveData = new MutableLiveData<>();
           mLiveData.observe(this, new Observer<String>() {
               @Override
               public void onChanged(String s) {
                   Log.i(TAG, "onChanged: "+s);
               }
           });
           Log.i(TAG, "onCreate: ");
           mLiveData.setValue("onCreate");//activity是非活跃状态,不会回调onChanged。变为活跃时,value被onStart中的value覆盖
       }
       @Override
       protected void onStart() {
           super.onStart();
           Log.i(TAG, "onStart: ");
           mLiveData.setValue("onStart");//活跃状态,会回调onChanged。并且value会覆盖onCreate、onStop中设置的value
       }
       @Override
       protected void onResume() {
           super.onResume();
           Log.i(TAG, "onResume: ");
           mLiveData.setValue("onResume");//活跃状态,回调onChanged
       }
       @Override
       protected void onPause() {
           super.onPause();
           Log.i(TAG, "onPause: ");
           mLiveData.setValue("onPause");//活跃状态,回调onChanged
       }
       @Override
       protected void onStop() {
           super.onStop();
           Log.i(TAG, "onStop: ");
           mLiveData.setValue("onStop");//非活跃状态,不会回调onChanged。后面变为活跃时,value被onStart中的value覆盖
       }
       @Override
       protected void onDestroy() {
           super.onDestroy();
           Log.i(TAG, "onDestroy: ");
           mLiveData.setValue("onDestroy");//非活跃状态,且此时Observer已被移除,不会回调onChanged
       }
    }
    

    log数据

    //打开页面,
    2020-11-22 20:23:29.865 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onCreate: 
    2020-11-22 20:23:29.867 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStart: 
    2020-11-22 20:23:29.868 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onStart
    2020-11-22 20:23:29.869 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onResume: 
    2020-11-22 20:23:29.869 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onResume
    //按Home键
    2020-11-22 20:23:34.349 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onPause: 
    2020-11-22 20:23:34.349 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onPause
    2020-11-22 20:23:34.368 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStop: 
    //再点开
    2020-11-22 20:23:39.145 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStart: 
    2020-11-22 20:23:39.146 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onStart
    2020-11-22 20:23:39.147 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onResume: 
    2020-11-22 20:23:39.147 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onResume
    //返回键退出
    2020-11-22 20:23:56.753 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onPause: 
    2020-11-22 21:23:56.753 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onPause
    2020-11-22 20:23:58.320 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onStop: 
    2020-11-22 20:23:58.322 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onDestroy: 
    

    1.首先打开页面,onCreate()中setValue,由于activity是非活跃状态,不会立即回调onChanged。当走到onStart()变为活跃时,onChanged被调用,但value被onStart()中setValue的value覆盖,所以打印的是onChanged: onStart。(为啥不是连续打印两次呢?,是因为ON_START事件是在onStart() return之后,即onStart()走完之后才变为活跃<详见上一篇>,此时observer接收最新的数据。) 接着走到onResume(),也setValue了,同样是活跃状态,所以立刻回调onChanged,打印onChanged: onResume

    2.按Home键时,onPause()中setValue,活跃状态,立刻回调onChanged方法。onStop()执行时已经变为非活跃状态,此时setValue不会立即回调onChanged方法。

    3.再点开时,走到onStart()变为活跃时,onChanged被调用,但value被onStart()中setValue的value覆盖,所以打印的是onChanged: onStart。接着走到onResume(),也setValue了,同样是活跃状态,所以立刻回调onChanged。

    4.返回键退出时,onPause()/onStop()的效果和按Home键一样。onDestroy()中setValue,此时非活跃状态,且此时observer已被移除,不会回调onChanged。

    另外,除了使用observe()方法添加观察者,也可以使用observeForever(Observer) 方法来注册未关联 LifecycleOwner的观察者。在这种情况下,观察者会被视为始终处于活跃状态。

    扩展使用

    • 自定义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);//移除股价更新的观察
            }
        }
    

    使用单利模式可以共享数据

    onActive()调用时机为:活跃的观察者(LifecycleOwner)数量从 0 变为 1 时。
    onInactive()调用时机为:活跃的观察者(LifecycleOwner)数量从 1 变为 0 时。
    也就是说,只有当 存在活跃的观察者(LifecycleOwner)时 才会连接到 股价更新服务 监听股价变化。使用如下:

      public class MyFragment extends Fragment {
            @Override
            public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
                super.onViewCreated(view, savedInstanceState);
                //获取StockLiveData单实例,添加观察者,更新UI
                StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> {
                    // Update the UI.
                });
            }
        }
    

    高级用法
    1.希望在将LiveData的数据 分发给使用跟着之前进行修改
    这种情况可以使用LiveData中提供的Transformations

          //Integer类型的liveData1
            MutableLiveData<Integer> liveData1 = new MutableLiveData<>();
            //转换成String类型的liveDataMap
            LiveData<String> liveDataMap = Transformations.map(liveData1, new Function<Integer, String>() {
                @Override
                public String apply(Integer input) {
                    String s = input + " + Transformations.map";
                    Log.i(TAG, "apply: " + s);
                    return s;
                }
            });
            liveDataMap.observe(this, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged1: "+s);
                }
            });
    
            liveData1.setValue(100);
    

    log

    2020-12-06 17:01:56.095 21998-21998/com.hfy.androidlearning I/LifecycleTest: apply: 100 + Transformations.map
    2020-12-06 17:01:56.095 21998-21998/com.hfy.androidlearning I/LifecycleTest: onChanged1: 1
    

    输入值 100 输入的值进行了 Transformations的转换 变为 100Transformations.map
    最终onChange的到的值 100Transformations.map
    2.数据切换 根据某个值判断 切换不用的liveDate对象 Transformations.switchMap

        //两个liveData,由liveDataSwitch决定 返回哪个livaData数据
            MutableLiveData<String> liveData3 = new MutableLiveData<>();
            MutableLiveData<String> liveData4 = new MutableLiveData<>();
    
        //切换条件LiveData,liveDataSwitch的value 是切换条件
            MutableLiveData<Boolean> liveDataSwitch = new MutableLiveData<>();
    
        //liveDataSwitchMap由switchMap()方法生成,用于添加观察者
            LiveData<String> liveDataSwitchMap = Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {
                @Override
                public LiveData<String> apply(Boolean input) {
                //这里是具体切换逻辑:根据liveDataSwitch的value返回哪个liveData
                    if (input) {
                        return liveData3;
                    }
                    return liveData4;
                }
            });
    
            liveDataSwitchMap.observe(this, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged2: " + s);
                }
            });
    
            boolean switchValue = true;
            liveDataSwitch.setValue(switchValue);//设置切换条件值
    
            liveData3.setValue("liveData3");
            liveData4.setValue("liveData4");
    

    log

    2020-12-06 17:33:53.844 27347-27347/com.hfy.androidlearning I/Lifecycle_Test: switchValue=true
    2020-12-06 17:33:53.847 27347-27347/com.hfy.androidlearning I/Lifecycle_Test: onChanged2: liveData3
    
    2020-12-06 17:34:37.600 27628-27628/com.hfy.androidlearning I/Lifecycle_Test: switchValue=false
    2020-12-06 17:34:37.602 27628-27628/com.hfy.androidlearning I/Lifecycle_Test: onChanged2: liveData4
    

    根据 switchValue. 的值判断去live3还是取live4
    3观察多个数据 - MediatorLiveData

            MediatorLiveData<String> mediatorLiveData = new MediatorLiveData<>();
    
            MutableLiveData<String> liveData5 = new MutableLiveData<>();
            MutableLiveData<String> liveData6 = new MutableLiveData<>();
    
        //添加 源 LiveData
            mediatorLiveData.addSource(liveData5, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged3: " + s);
                    mediatorLiveData.setValue(s);
                }
            });
        //添加 源 LiveData
            mediatorLiveData.addSource(liveData6, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged4: " + s);
                    mediatorLiveData.setValue(s);
                }
            });
    
        //添加观察
            mediatorLiveData.observe(this, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged5: "+s);
                    //无论liveData5、liveData6更新,都可以接收到
                }
            });
    
            liveData5.setValue("liveData5");
            //liveData6.setValue("liveData6");
    

    log

    2020-12-06 17:56:17.870 29226-29226/com.hfy.androidlearning I/Lifecycle_Test: onChanged3: liveData5
    2020-12-06 17:56:17.870 29226-29226/com.hfy.androidlearning I/Lifecycle_Test: onChanged5: liveData5
    

    当一个数据源改变是 会触发多个LiveData的改变
    LiveData 源码解析

    添加观察者

        @MainThread
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            assertMainThread("observe");
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                // LifecycleOwner是DESTROYED状态,直接忽略
                return;
            }
            //使用LifecycleOwner、observer 组装成LifecycleBoundObserver,添加到mObservers中
            LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
            ObserverWrapper existing = mObservers中.putIfAbsent(observer, wrapper);
            if (existing != null && !existing.isAttachedTo(owner)) {
            //!existing.isAttachedTo(owner)说明已经添加到mObservers中的observer指定的owner不是传进来的owner,就会报错“不能添加同一个observer却不同LifecycleOwner”
                throw new IllegalArgumentException("Cannot add the same observer"
                        + " with different lifecycles");
            }
            if (existing != null) {
                return;//这里说明已经添加到mObservers中,且owner就是传进来的owner
            }
            owner.getLifecycle().addObserver(wrapper);
        }
    

    在添加数据观察的时候首先判断当前的状态 如果当前的活跃状态是DESTROYED则直接忽略不进行添加
    LifecycleOwner、observer 组装成LifecycleBoundObserver包装实例wrapper,使用putIfAbsent方法observer-wrapper作为key-value添加到观察者列表mObservers中
    然后对添加的结果进行判断,如果mObservers中已经存在此observer key,但value中的owner不是传进来的owner,就会报错“不能添加同一个observer却是不同LifecycleOwner”。如果是相同的owner,就直接return;

    2.事件回调
    我们为liveData添加了观察者LifecycleBoundObserver,事件的回调就在 LifecycleBoundObserver中 接下来我们看一下 LifecycleBoundObserver的源码

      class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
            @NonNull
            final LifecycleOwner mOwner;
    
            LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
                super(observer);
                mOwner = owner;
            }
    
            @Override
            boolean shouldBeActive() { //至少是STARTED状态
                return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
            }
    
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                    removeObserver(mObserver);//LifecycleOwner变成DESTROYED状态,则移除观察者
                    return;
                }
                activeStateChanged(shouldBeActive());
            }
    
            @Override
            boolean isAttachedTo(LifecycleOwner owner) {
                return mOwner == owner;
            }
    
            @Override
            void detachObserver() {
                mOwner.getLifecycle().removeObserver(this);
            }
        }
    

    LifecycleBoundObserver是LiveData的内部类,是对原始Observer的包装,把LifecycleOwner和Observer绑定在一起。当LifecycleOwner处于活跃状态,就称 LifecycleBoundObserver是活跃的观察者,
    它实现自接口LifecycleEventObserver,实现了onStateChanged方法可以感知生命周期状态变化的回调
    在LifecycleOwner生命周期状态变化时 判断如果是DESTROYED状态,则移除观察者。LiveData自动移除观察者特点就来源于此 如果不是DESTROYED状态,将调用父类ObserverWrapper的activeStateChanged()方法处理 这个生命周期状态变化,shouldBeActive()的值作为参数,至少是STARTED状态为true,即活跃状态为true

        private abstract class ObserverWrapper {
            ...
            void activeStateChanged(boolean newActive) {
                if (newActive == mActive) {
                    return;//活跃状态 未发生变化时,不会处理。
                }
                mActive = newActive;
                boolean wasInactive = LiveData.this.mActiveCount == 0;//没有活跃的观察者
                LiveData.this.mActiveCount += mActive ? 1 : -1;//mActive为true表示变为活跃
                if (wasInactive && mActive) {
                    onActive();//活跃的观察者数量 由0变为1
                }
                if (LiveData.this.mActiveCount == 0 && !mActive) {
                    onInactive(); //活跃的观察者数量 由1变为0
                }
                if (mActive) {
                    dispatchingValue(this);//观察者变为活跃,就进行数据分发
                }
            }
        }
    

    在 ObserverWrapper 中判断 只有在当前界面就是活跃状态的时候才会进行分发

       void dispatchingValue(@Nullable ObserverWrapper initiator) {
            if (mDispatchingValue) {
                mDispatchInvalidated = true;//如果当前正在分发,则分发无效,return
                return;
            }
            mDispatchingValue = true; //标记正在分发
            do {
                mDispatchInvalidated = false; 
                if (initiator != null) {
                    considerNotify(initiator); //observerWrapper不为空,使用considerNotify()通知真正的观察者
                    initiator = null;
                } else { //observerWrapper为空,遍历通知所有的观察者
                    for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                            mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                        considerNotify(iterator.next().getValue());
                        if (mDispatchInvalidated) {
                            break;
                        }
                    }
                }
            } while (mDispatchInvalidated);
            mDispatchingValue = false; 
        }
    

    如果当前正在分发择分发无效,observerWrapper不为空,就使用considerNotify()通知真正的观察者,
    如果当前正在分发,则分发无效;observerWrapper不为空,就使用considerNotify()通知真正的观察者,observerWrapper为空 则遍历通知所有的观察者

        private void considerNotify(ObserverWrapper observer) {
            if (!observer.mActive) {
                return; //观察者非活跃 return
            }
            //若当前observer对应owner非活跃,就会再调用activeStateChanged方法,并传入false,其内部会再次判断
            if (!observer.shouldBeActive()) {
                observer.activeStateChanged(false);
                return;
            }
            if (observer.mLastVersion >= mVersion) {
                return;
            }
            observer.mLastVersion = mVersion;
            observer.mObserver.onChanged((T) mData);//回调真正的mObserver的onChanged方法
        }
    

    先进行状态检查:观察者是非活跃就return;若当前observer对应的owner非活跃,就会再调用activeStateChanged方法,并传入false,其内部会再次判断。最后回调真正的mObserver的onChanged方法,值是LivaData的变量mData
    更新数据 setValue()

       protected void setValue(T value) {
            assertMainThread("setValue");
            mVersion++;
            mData = value;
            dispatchingValue(null);
        }
    

    dispatchingValue(null) 更新数据并通知 所有正在活跃的观察者

    相关文章

      网友评论

          本文标题:jetapck 学习 LiveData

          本文链接:https://www.haomeiwen.com/subject/gewkcltx.html