Jetpack-LiveData(面试深度起来)

前言

4202年了,谁还用`LiveData`,X都不用。

我也是这么想的,然后经历面试三联:

  • LiveData 用过吧?setValue()posValue()有啥区别?原理是啥?
  • observe()observeForever()知道么? 原理是啥,数据是怎么分发的?
  • LiveData 黏性知道怎么肥事吗?原理是啥?怎么解决?

我: 用过,post不用管线程。observeForever()一直等。黏性我看过 有个version 的原因。

面试官:你回去等消息吧。 然后面试评价 :基础不牢,深度不够。

基础用法

  var testLiveData = MutableLiveData<String>()
  //数据发送
        testLiveData.setValue("")//主线程设置
        testLiveData.postValue("")//可以在任何线程(包括后台线程)中调用
 //数据接收
 
   viewModel?.testLiveData?.observe(this){
     //活动状态接收
        }
        viewModel?.testLiveData?.observeForever {
          //不受 LifecycleOwner 生命周期的影响 要注意内存泄露
          
        }
​
​

有深度(顺利装逼)回答

setValue()postValue()的区别
@Override
    public void setValue(T value) {
      //调用父类方法
        super.setValue(value);
    }
​
 @MainThread
    protected void setValue(T value) {
      //判断是否主线程
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
​
static void assertMainThread(String methodName) {
  //异常抛出
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }

setValue()LiveData() 里 会判断当前线程是否是主线程,如果不是直接异常抛出。

postValue() 为啥可以?

@Override
    public void postValue(T value) {
        super.postValue(value);
    }
​
​
​
 protected void postValue(T value) {
        boolean postTask;
        //加锁
        synchronized (mDataLock) {
          //如果当前mPendingData == 没设置
            postTask = mPendingData == NOT_SET;
          //mPendingData就等于新塞进来的数据
            mPendingData = value;
        }
        if (!postTask) {
          //如果当前 postTask 是false 也就说当前 不是NOT_SET状态 直接返回
            return;
        }
   
    //发送数据    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
​
​
​
//  setValue
   private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };
​
  @Override
    public void postToMainThread(@NonNull Runnable runnable) {
      //主线程 post 数据
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = createAsync(Looper.getMainLooper());
                }
            }
        }
        //noinspection ConstantConditions
        mMainHandler.post(runnable);
    }

看完这些基础代码,大体明白,postValue()就是丢了一个Runnable给了主线程。所以他可以任意线程发送,但是主线程执行。我们看到postValue() 里面有个return, 所以大家常说 数据过快,会丢数据的原因,其实就是!postTask return 导致。

observe()observeForever()
  • observe()
//初始化缓存
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =new SafeIterableMap<>();
 
​
@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
      //检查是主线程么
        assertMainThread("observe");
        //检查当前是不是 DESTROYED
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }
      //构建 LifecycleBoundObserver
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
      //判断是否需要执行的时候 已经缓存过了 再判断缓存的observer 是否已经添加到其他lifecycles  命中则直接扔异常 
        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);
    }
​
//  如果已经存入返回缓存 否则返回null
  public V putIfAbsent(@NonNull K key, @NonNull V v) {
        Entry<K, V> entry = get(key);
        if (entry != null) {
            return entry.mValue;
        }
        put(key, v);
        return null;
    }
​
​

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() {
            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);
        }
    }

这里梳理下:

LiveData 里有一个mObservers 是一个Map,在我们 调用 observe()方法的时候,

第一步 :先判断当前线程,非主线程则抛出异常。

第二步:看当前 LifecycleOwner 的生命周期,是否属于活动状态 ,否则retrun

第三步:构建LifecycleBoundObserver,构造函数里 将 传入的ower复制给自己内部mOwner

调用putIfAbsent(),以observerkey 去查询 是否已经缓存,如果已缓存返回value。无则缓存进去并,返回null

紧接着判断 如果当前observer 已经缓存了,并且和之前缓存进去的owner 不是一个,那就直接异常。告知一个observer 不能绑定不同的lifeclycle。 确保observerowner 一一对应。

第四步:返回值 不为null 。直接返回,避免重复绑定。

第五步:ower 开始监听生命周期。

这里的第三步,正反查其实是很有意思的一个代码。

  • observeForever
    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
      //主线程检查
        assertMainThread("observeForever");
      //创建AlwaysActiveObserver
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
      //如果已经绑定 则异常抛出
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        wrapper.activeStateChanged(true);
    }

observeForever()相对看起来简单一些

第一步 :先判断当前线程,非主线程则抛出异常。

第二步:构建AlwaysActiveObserver,构造函数里 将 传入的ower 复制给自己内部mOwner

调用putIfAbsent(),以observerkey去查询 是否已经缓存,如果已缓存返回value。无则缓存进去并,返回null

紧接着判断 如果当前observer已经缓存了,如果已经缓存的是一个LifecycleBoundObserver ,也就是监听生命周期的, 抛出异常。

第三步:返回值 不为null。直接返回,避免重复绑定。

第四步:调用activeStateChanged(),这里需要看一下 因为下面没代码了。

 void activeStateChanged(boolean newActive) {
   // newActive 默认false
            if (newActive == mActive) {
                return;
            }
            mActive = newActive;
   // 传入1
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                //分发数据 将自己也就是上文的AlwaysActiveObserver 传入进去
                dispatchingValue(this);
            }
        }

void dispatchingValue(@Nullable ObserverWrapper initiator) {
  
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            //因为我们传了this  不为null 所以走considerNotify
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, 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;
        }
  
          // AlwaysActiveObserver 的shouldBeActive 返回是true
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
      // 判断版本 这个后面说
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
         //不管上面的代码,直接看这一句,回调数据
        observer.mObserver.onChanged((T) mData);
    }

这里简单的跑了一下流程 ,就知道 数据会被回调。至于怎么回调还不知道。

  • 总结

    • observe 构建 LifecycleBoundObserver ,会进行生命周期的相关拦截处理。
    • observeForever 构建 AlwaysActiveObserver
    • 两种都会保证相对的唯一性,在绑定之前都会检查是否是在主线程。
数据是怎么分发的?

关于数据的分发 ,我们还是要回到setValue()postValue()

setValue() 的数据分发
 @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    } 

似乎分发数据的只有dispatchingValue(),追进去看一下

​
    @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 {
               //因为我们传入是个null走这里 上面直接不看 
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                  //发现 哎呦 怎么又走了considerNotify()方法。
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

因为我们传入是个null,else, 我们发现这里代码意思就是 遍历 mObservers 取值,调用

considerNotify() 再次看一下这个方法。

 @SuppressWarnings("unchecked")
    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
 
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

ObserverWrapper 是从哪里来的? 需要我们思考一下。

其实很简单 调用 observe()observeForever() 的时候 往mObservers存入进去。

ObserverWrapperobserve 里 是 LifecycleBoundObserverobserveForeverAlwaysActiveObserver

继续回看 considerNotify() , 这里observerLifecycleBoundObserver

调用 observer.mActive ,我们看下 mActive 是怎么来的。

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() {
            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);
        }
    }

private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;
​
        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }
​
        abstract boolean shouldBeActive();
​
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }
​
        void detachObserver() {
        }
​
        //被 LifecycleBoundObserver 的 onStateChanged 影响
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
​
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

LifecycleBoundObserver 使用父类 ObserverWrapper中的 mActive

newActiveactiveStateChanged() 影响, 回看 LifecycleBoundObserveronStateChanged 方法。LifecycleBoundObserver 实现 LifecycleEventObserver监听生命周期,会回调onStateChanged()shouldBeActive()表明起码在onStart()onPause()之前。才返回true。 这里while 会将当前状态再次配平。

再次回到 considerNotify() ,接下来的shouldBeActive()我们知道其实就是看当前是否在活动状态,紧接着

 if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);

这个 mLastVersionmVersion是什么?

 static final int START_VERSION = -1;
private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;}
​
​
//mVersion 是liveData 属性
 public LiveData(T value) {
        mData = value;
        mVersion = START_VERSION + 1;
    }
    public LiveData() {
        mData = NOT_SET;
        mVersion = START_VERSION;
    }

START_VERSION默认为-1observer里的值 默认为 START_VERSION,而LiveData构建的时候 ,如果传了值则默认为 START_VERSION + 1 ,否则为START_VERSION

追看一下代码,发现ObserverWrapper 中的mLastVersion,除了初始值外,只有considerNotify() 方法中,会赋值。

mVersionliveData 调用setValue()方法的时候 会++

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

至此 大体流程跑通,

LiveData 调用setValue()mVersion ++,此刻从-10

调用dispatchingValue(null);

mObservers遍历所有缓存,判断如果当前页面还在活动,

如果ObserverWrapper 内置的 mLastVersionLiveDatamVersion(默认为-1)小 则回调执行,且赋值相等。

postValue() 的数据分发
  protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

在前面我们讲过,其实原理mMainHandler.post(runnable); 将线程切换到了主线程。

我们关注下 mPostValueRunnable做了什么。

  private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
              //重新设置回NOT_SET
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

newValue 是为了在主线程中安全地传递并应用非主线程中提交的待更新值。

紧接着 调用 setValue() 调用 dispatchingValue()

这次要走上面

   @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<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

继续 调用 considerNotify()

private void considerNotify(ObserverWrapper observer) {
    //AlwaysActiveObserver 
        if (!observer.mActive) {
            return;
        }
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

这里的observer其实是AlwaysActiveObserver ,第一步判断.mActive(),我们之前看到

该值 受 activeStateChanged() 影响。

​
    private class AlwaysActiveObserver extends ObserverWrapper {
​
        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }
​
        @Override
        boolean shouldBeActive() {
            return true;
        }
    }
​
    static void assertMainThread(String methodName) {
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }

而我们在observeForever()方法中 直接设置为了true

  @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
      //设置为true
        wrapper.activeStateChanged(true);
    }

接下来 调用 shouldBeActive()AlwaysActiveObserver返回true,不进入

紧接着 对比了mLastVersionmVersion, 回调onChanged()

总结一下:

第一步:将mPostValueRunnable切换子线程。

第二步: 赋值给newValuemPendingData 重置,调用setValue()

第三步: mVersion++; 调用dispatchingValue()

第四步:走非空逻辑,调用considerNotify(initiator)

第五步:闯过2个判断,判断mLastVersionmVersion ,数据分发onChanged()

LiveData 的问题相关
数据倒灌问题

其实理论上来说,我认为这并不是一个问题,但是讲下什么情况会出现的原因

当新的观察者开始注册的时候,会将最后一次数据发送给当前。(当前页面是活动状态时候)

我们看下LifecycleBoundObserver,while 这里 第一次肯定是不相等,则必定走

activeStateChanged()

  @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();
            }
        }

activeStateChanged 里走了 dispatchingValue()

继续走了 considerNotify()

if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);

因为observer是新的,则默认mLastVersion-1,此刻liveData 内部有数据,肯定会回调一次。 然后配平mLastVersionmVersion

至于怎么解决,网上有很多方案。大家可自行百度 /谷歌。篇幅原因,不在赘述。

postValue()丢数据问题

在上面代码我们看到,postValue()是将数据post到主线程。等到执行才重置,才可以再次赋值。那在主线程未执行之前,就会丢数据。所以连续搞多次,可能就丢数据了。

protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
          //原因在这
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
​
  private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

错过数据更新

如果在ActivityFragment的较晚生命周期阶段(如onResume()之后)注册观察者,那么在这之前设置的LiveData数据将不会被观察到,因为观察者错过了数据初次变更的通知。

这个可以参考源码里面的LifecycleBoundObserver.shouldBeActive() 方法。

最后

虽然在4202年的今天,LiveData已经算比较落伍(捂脸我之前公司还在用),但是其中的源码解读,还是很有必要。

没有不好的框架,只有不好的代码。还是希望大家出去面试的时候,能够熟练的装X,维护住个人的巨佬形象,切莫学我,被人评价深度不够,回家吃灰。

如果你看到了这里,觉得文章写得不错就给个赞呗?
更多Android进阶指南 可以扫码 解锁更多Android进阶资料


在这里插入图片描述
敲代码不易,关注一下吧。ღ( ´・ᴗ・` )

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值