jetapck 学习 LiveData

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 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() {
           @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 {
        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 liveData1 = new MutableLiveData<>();
        //转换成String类型的liveDataMap
        LiveData liveDataMap = Transformations.map(liveData1, new Function() {
            @Override
            public String apply(Integer input) {
                String s = input + " + Transformations.map";
                Log.i(TAG, "apply: " + s);
                return s;
            }
        });
        liveDataMap.observe(this, new Observer() {
            @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 liveData3 = new MutableLiveData<>();
        MutableLiveData liveData4 = new MutableLiveData<>();

    //切换条件LiveData,liveDataSwitch的value 是切换条件
        MutableLiveData liveDataSwitch = new MutableLiveData<>();

    //liveDataSwitchMap由switchMap()方法生成,用于添加观察者
        LiveData liveDataSwitchMap = Transformations.switchMap(liveDataSwitch, new Function>() {
            @Override
            public LiveData apply(Boolean input) {
            //这里是具体切换逻辑:根据liveDataSwitch的value返回哪个liveData
                if (input) {
                    return liveData3;
                }
                return liveData4;
            }
        });

        liveDataSwitchMap.observe(this, new Observer() {
            @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 mediatorLiveData = new MediatorLiveData<>();

        MutableLiveData liveData5 = new MutableLiveData<>();
        MutableLiveData liveData6 = new MutableLiveData<>();

    //添加 源 LiveData
        mediatorLiveData.addSource(liveData5, new Observer() {
            @Override
            public void onChanged(String s) {
                Log.i(TAG, "onChanged3: " + s);
                mediatorLiveData.setValue(s);
            }
        });
    //添加 源 LiveData
        mediatorLiveData.addSource(liveData6, new Observer() {
            @Override
            public void onChanged(String s) {
                Log.i(TAG, "onChanged4: " + s);
                mediatorLiveData.setValue(s);
            }
        });

    //添加观察
        mediatorLiveData.observe(this, new Observer() {
            @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 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 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, 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)