jetpack分析2:livedata分析

50 阅读5分钟

问题思考

  • livedata如何观察数据
  • livedata怎么感知生命周期
  • 为啥livedata他是粘性数据

1.如何实现数据监听

  livedata基本使用是通过observe监听,然后setValue/postValue进行通知,先从主线路开始分析

 // 完整写法 new  Observer  onChanged
MyLiveData.info1.observe(this, object: Observer<String> {
    override fun onChanged(t: String?) {
        textView.text = t // 更新UI
    }
})

MyLiveData.info1.setValue\postValue("我是刷新数据")

   看下livedata如何监听数据先。可以看下面代码,重点关注LifecycleBoundObserver,它实际就是lifecycleOwner+observer的包装类(为啥要传lifecycleOwner,实际就是为了监听生命周期,先埋下伏笔)。生成之后用mObservers缓存

// 这部分代码将obser封装,并添加都mObservers作为缓存,
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> 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); // 添加到了lifecycle里了
}

   上面是添加了订阅者,那我们再看看怎么触发这个订阅者,从setValue开始看

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

// 大头主要是这个方法,可以从这个方法反查,主要有2个地方,一个传null(setValue),一个传参数(初始化),
// 初始化的时候也是会调用这个方法,这就是为什么livedata会有粘性
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(); ) {
                // 通过setValue 触发,然后告诉订阅者
                considerNotify(iterator.next().getValue()); 
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

// 触发回调了
private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // 感知生命周期,如果是非活跃状态就return
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    // 粘性代码控制条件
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    //noinspection unchecked
    // 重点代码:就是这代码触发观察者的回调,
    observer.mObserver.onChanged((T) mData);
}

   可以看到我们通过setValue->dispatchingValue->considerNotify->observer.mObserver.onChanged。这就是数据更新通知回调的整个流程。

if (!observer.shouldBeActive()) 注意看这个代码,为啥我们的livedata感知生命周期,要在onStart\onResume状态才能更新ui,就是这个判断的,下面看看这个代码实现

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

2. 为啥回到活跃状态,数据能重新触发回调

  这个涉及到了lifecycle,LivecycleRegistry内部类OBServerWithState的dispathEvent方法不知道有印象吗,这里重新再弄出来给大家看看

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;

    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        //mLifecycleObserver 是不是很熟悉
        mLifecycleObserver.onStateChanged(owner, event); 
        mState = newState;
    }
}

  LiveData里面有一个LifecycleBoundObserver,这玩意不就是一开始说的对lifecycleOwner+observer的封装吗,并且被lifecycle对象add()了。上面的mLifecycleObserver代码就是LifecycleBoundObserver,那最后又触发了LifecycleBoundObserver下面的onStateChanged()

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
    @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(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive()); // 重点代码
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}
    
// ObserverWrapper.java
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() {
    }

    //核心代码
    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        mActive = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += mActive ? 1 : -1;
        if (wasInactive && mActive) {
            onActive();
        }
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            onInactive();
        }
        if (mActive) {
            dispatchingValue(this); // 是不是又触发了,
        }
    }
}

   总结下上面代码:实际是通过lifecycle生命周期改变,触发了LifecycleBoundObserver的onStateChanged的方法,接着调用它父类的activeStateChanged(),最后又回到dispatchingValue(this)的方法,又回到第一个步骤的内容了

3.为啥是粘性数据

   其实从上面已经看到粘性代码这块了,用直白的话术表达:一个Livedata对象,他先设置了setValue ,mVersion已经自增一次过了。但是还没有添加observer,所以dispatchingValue()遍历observer的时候不满足条件,就没办法调用considerNotify更新数据。

protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;  // 自增一次,mVersion默认是-1
    mData = value;
    dispatchingValue(null);
}

  等下一次observer()添加了又重新触发considerNotify,前面知道了mVersion自增过(大于-1),而observer.mLastVersion默认-1 是小于mVersion,所以并没有return出去,而是直接调用了observer.mObserver.onChanged,这就是我们粘性的根本原因

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    // 如果是粘性数据,那么mVersion前面自增过,observer.mLastVersion又没有自增过,所以会直接return
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion; // 这里重新复制
    //noinspection unchecked
    observer.mObserver.onChanged((T) mData);
}

4.如何干掉粘性数据

  只需要想办法在observer()新增订阅者的时候,吧 observer.mLastVersion和mVersion 搞成一样就可以了。提供一个完整的例子

/**
 * 单例模式 去掉黏性事件(有关闭黏性的开关) KT的版本
 */
object OKLiveDataBusKT {

    // 存放订阅者
    private val bus : MutableMap<String, BusMutableLiveData<Any>> by lazy { HashMap() }

    // 暴露一个函数,给外界注册 订阅者关系
    @Synchronized
    fun <T> with(key: String, type: Class<T>, isStick: Boolean = true) : BusMutableLiveData<T> {
        if (!bus.containsKey(key)) {
            bus[key] = BusMutableLiveData(isStick)
        }
        return bus[key] as BusMutableLiveData<T>
    }

    // Any? 是 Object ,  * 星投影 KT泛型的?  有点像 Java ?
    class BusMutableLiveData<T> private constructor() : MutableLiveData<T>() {

        var isStick: Boolean = false

        // 次构造
        constructor(isStick: Boolean) : this() {
            this.isStick = isStick
        }

        // 我是先执行
        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer) // 这句会执行父类的  // 启用系统的功能  不写就破坏了

            if (!isStick) {
                hook(observer = observer)
                Log.d("derry", "Kotlin版本的 不启用黏性")
            } else {
                Log.d("derry", "Kotlin版本的 启用黏性")
            }
        }

        private fun hook(observer: Observer<in T>) {
            // TODO 1.得到mLastVersion
            // 获取到LivData的类中的mObservers对象
            val liveDataClass = LiveData::class.java

            val mObserversField: Field = liveDataClass.getDeclaredField("mObservers")
            mObserversField.isAccessible = true // 私有修饰也可以访问

            // 获取到这个成员变量的对象  Any == Object
            val mObserversObject: Any = mObserversField.get(this)

            // 得到map对象的class对象   private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            val mObserversClass: Class<*> = mObserversObject.javaClass

            // 获取到mObservers对象的get方法   protected Entry<K, V> get(K k) {
            val get: Method = mObserversClass.getDeclaredMethod("get", Any::class.java)
            get.isAccessible = true // 私有修饰也可以访问

            // 执行get方法
            val invokeEntry: Any = get.invoke(mObserversObject, observer)

            // 取到entry中的value   is "AAA" is String    is是判断类型 as是转换类型
            var observerWraper: Any? = null
            if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
                observerWraper = invokeEntry.value
            }
            if (observerWraper == null) {
                throw NullPointerException("observerWraper is null")
            }

            // 得到observerWraperr的类对象
            val supperClass: Class<*> = observerWraper.javaClass.superclass
            val mLastVersion: Field = supperClass.getDeclaredField("mLastVersion")
            mLastVersion.isAccessible = true

            // TODO 2.得到mVersion
            val mVersion: Field = liveDataClass.getDeclaredField("mVersion")
            mVersion.isAccessible = true

            // TODO 3.mLastVersion=mVersion
            val mVersionValue: Any = mVersion.get(this)
            mLastVersion.set(observerWraper, mVersionValue)
        }
    }

}