美文网首页
LiveData源码篇

LiveData源码篇

作者: Method | 来源:发表于2021-01-06 13:10 被阅读0次
gyy1.jpg

序言

我们知道Livedata可以监听生命周期发送数据,并且采用的是观察者模式,看源码前先思考几个问题

  • 怎么观察生命周期状态?
  • 为什么可发送粘性事件?
  • 当重新可见的时候会不会重新接收到数据?怎么做到的?
  • 触发多个生命周期方法,观察者会不会多次收到信息?怎么控制这块的?
  • 怎么多个Activity共用同一个Livedata?
  • AActivity发送消息,BActivity注册能收到数据吗?
  • AActivity注册在BActivity#Oncreat()发送,Activity 会收到消息么?
  • AActivity注册在BActivity#点击事件发送,Activity 会收到消息么

按照创建->添加观察者->发送数据流程对Livedata分析

1.创建做了什么?

  public MutableLiveData() {
         super();
  }
     
  public LiveData() {
      //mData保存我们发送的数据
      mData = NOT_SET;
      mVersion = START_VERSION;
  }  

2.添加观察者做了什么?

  public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //判断是否是主线程,否则报异常
        assertMainThread("observe");
        //判断当前界面是否销毁
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //将livedata观察者和own封装到LifecycleBoundObserver
        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);
    }

LifecycleBoundObserver是什么?

从名字可以看出是将组件(Activity、fragment)的生命周期绑定到观察者上,看源码

  //实现了LifecycleEventObserver
  class LifecycleBoundObserver extends ObserverWrapper   implements LifecycleEventObserver {
          //当Activity的生命周期改变就会触发这个方法
          @Override
          public void onStateChanged(@NonNull LifecycleOwner   source,
                  @NonNull Lifecycle.Event event) {
              if (mOwner.getLifecycle().getCurrentState() ==   DESTROYED) {
                  removeObserver(mObserver);
                  return;
              }
              activeStateChanged(shouldBeActive());
          }
      }

3.发送数据做了什么

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    //将任务放到线程池里 并切换到主线程
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

postvalue其实就是切换到主线程并调用setValue发送数据

private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        //其实调用的也是setValue发送数据
        setValue((T) newValue);
    }
};
@MainThread
protected void setValue(T value) {
    //不是主线程抛出异常
    assertMainThread("setValue");
    //记录数据发送次数
    mVersion++;
    //将发送的数据赋值给mData
    mData = value;
    //默认传null
    dispatchingValue(null);
}

遍历所有观察者

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;
}
private void considerNotify(ObserverWrapper observer) {
    //判断是否可见
    if (!observer.mActive) {
        return;
    }
    //回调观察者前 判断观察者是否时active状态  否则不会回调onChanged方法
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    //防止生命周期回调多次  多次触发onChanged方法
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    //回调观察者onChaged方法
    observer.mObserver.onChanged((T) mData);
}

到此一个基本流程结束,其实就是运用了观察者模式。首先注册观察者,然后将观察者缓存到一个map里。当收到数据时会遍历所有的观察者,判断可见性,如果可见就通知观察者更新。

问题

问题一:怎么观察生命周期状态?

livedata添加观察者时,会创建一个LifecycleBoundObserver,它是一个组件生命周期观察者,当生命周期改变时,会触发onStateChanged,然后LifecycleBoundObserver会判断生命周期是否是isActive去调用观察者更新。与其说livedata观察生命周期,不如说是通过LifecycleBoundObserver观察。

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        ...
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ...
        owner.getLifecycle().addObserver(wrapper);
    }
public void onStateChanged(@NonNull LifecycleOwner   source,
                  @NonNull Lifecycle.Event event) {
              if (mOwner.getLifecycle().getCurrentState() ==   DESTROYED) {
                  removeObserver(mObserver);
                  return;
              }
              activeStateChanged(shouldBeActive());
          }

继续看 activeStateChanged做了什么

  void activeStateChanged(boolean newActive) {
           ...
            //判断生命周期是否是可见的
            if (mActive) {
                dispatchingValue(this);
            }
    }

问题二:为什么可发送粘性事件?

在onCreat中发送数据,点击按钮再去注册观察者

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_livedata_code)
    //发送数据
    liveData.postValue("1111111111")
}
//按钮点击
fun sendData(view: View) {
    //添加观察者
    liveData.observe(this, Observer {
        Log.i(TAG, "livedata---------------->$it");
    }) 
}

结果成功打印

I/LiveDataCodeAcy: livedata---------------->1111111111

liveData.observe 会调用 owner.getLifecycle().addObserver(wrapper);
因为LifecycleBoundObserver 间接实现了LifecycleObserver 所以会回调onStateChange()方法,在此方法中会重新遍历所有可见的观察者,触发更新

@Override
public void onStateChanged(@NonNull LifecycleOwner source,
        @NonNull Lifecycle.Event event) {
    //是否时Destory状态
    if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
        //是的 就从map里删除此观察者
        removeObserver(mObserver);
        return;
    }
    activeStateChanged(shouldBeActive());
}
void activeStateChanged(boolean newActive) {
    if (mActive) {
        //这里和setvalue一样调用了 dispatchingValue 参数是this
        dispatchingValue(this);
    }
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    
    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;
}
@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;
    //重新调用观察者的onChanged方法
    observer.mObserver.onChanged((T) mData);
}

所以发送数据的地方有两个地方

1.setValue()\postValue()

2.oberver()

问题三:当重新可见的时候会不会重新接收到数据?怎么做到的?

同理会触发LifecycleBoundObserver#onStateChanged(),然后重新遍历可见的观察者更新

问题四:触发多个生命周期方法,观察者会不会多次收到信息?怎么控制这块的?

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);
    }
protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
}

利用mVersion来记录是否处理过这个数据

  1. mVersion、mLastVersion 初始值都是-1
  2. 当setValue mVersion++ 变成1,observer.mLastVersion >= mVersion不成立,mLastVersion 变成1,然后回调方法
  3. 当生命周期发生改变,回调此方法observer.mLastVersion = mVersion。所以就不会继续触发回调方法
  4. 再次有生命周期方法触发 也不会多次触发观察者回调方法

问题五:怎么多个Activity共用同一个Livedata?

class LiveDataUtils {
    private lateinit var mLiveDataMap:MutableMap<String,MutableLiveData<Any>>
    private constructor(){
        mLiveDataMap = mutableMapOf()
    }

    companion object{
        private  val instance = LiveDataUtils()
        fun getInstance():LiveDataUtils{
            return instance
        }
    }
    /**
     * 1.保存
     * 2.获取
     */
    fun <T> with(key:String,clazz:Class<T>) : MutableLiveData<T>{
        if(!mLiveDataMap.containsKey(key)){
            mLiveDataMap[key] = MutableLiveData<Any>()
        }
        return mLiveDataMap[key] as MutableLiveData<T>
    }
}

问题六:AActivity发送消息,BActivity注册能收到数据吗?

AActivity

livedata = LiveDataUtils.getInstance().with("login",String::class.java)
livedata.postValue("来自AActivity的message")

BActivity

livedata.observe(this, Observer {
    Log.i(TAG, "twoActivity:$it");
})

打印

twoActivity:来自AActivity的message

答案是肯定的,和问题二一个道理。当BActivity observe时,会触发生命周期方法回调,然后遍历所有观察者更新

问题七:AActivity注册在BActivity#Oncreat()发送,Activity 会收到消息么?

AActivity

livedata.observe(this, Observer {
    Log.i(TAG, "AActivity:$it");
})

BActivity # onCreate

livedata.postValue("来自BActivity的message")

打印

AActivity:来自BActivity的message

原因是在BActiviy#Oncreat(),Livedata认为Activity还是可见的

问题八:AActivity注册在BActivity#点击事件发送,Activity 会收到消息么

AActivity

livedata.observe(this, Observer {
    Log.i(TAG, "oneActivity:$it");
})

BActivity # 方法中

livedata.postValue("来自twoActivity的message")

打印

因为当发送给观察者时会判断组件所处的生命周期
//回调观察者前 判断观察者是否时active状态 否则不会回调onChanged方法

if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }

当在oncreate中 livedata认为是可见状态,所以能收到。再方法中发送消息,这时候生命周期认为是不可见的 所以没有调用

相关文章

网友评论

      本文标题:LiveData源码篇

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