美文网首页
Jetpack LiveData

Jetpack LiveData

作者: Drew_MyINTYRE | 来源:发表于2022-03-25 09:58 被阅读0次

遵循 通过唯一可信源分发状态 的标准化开发理念。唯一可信源是指 生命周期独立于 视图控制器的 数据组件,通常是 单例 或共享 ViewModel。

EventBus 只是纯粹的 Bus,它 缺乏上述提到的 标准化开发理念 的约束,造成 诸如 毫无防备地收到 预期外的 不明来源的推送、拿到过时的数据 及 事件源追溯复杂度 为 n² 的局面。

EventBus 本身缺乏 Lifecycle 的加持,存在生命周期管理的一致性问题。这是 EventBus 的硬伤,也是我拒绝使用 EventBus 的最主要因素。

LiveData 是在 Google 希望确立 标准化、规范化 的开发模式,Google 十分克制地将其设计为,仅支持 状态 的输入和监听,从而,它不得不 在单例的配合下,承上启下地完成 状态 从 唯一可信源 到 视图控制器 的输送。

LiveData 有个坑需要注意,在视图控制器发生重建后,能够 自动倒灌 所观察的 LiveData 的最后一次数据,LiveData 被设计为粘性事件。

关于非粘性 LiveData 的实现,网上存在通过 “事件包装类”(只适合 kotlin 的情况) 和 “反射干预 LastVersion” (适用于 Java 的情况)两种方式来解决:

事件包装类

反射干预 LastVersion

无论是使用哪一种实现,我都建议 遵循传统 LiveData 所遵循的开发理念,通过唯一可信源分发状态,来方便事件源头的追溯。

SingleLiveEvent.java 的问题在于它仅限于一个观察者。如果您无意中添加了多个,则只会调用一个,并且不能保证哪一个。(推荐: 使用事件包装器,在这种方法中,您可以明确地管理事件是否已经被处理,从而减少错误。他们现在只是一个消耗或者不消耗的消息。)

总之:把事件设计成你的状态的一部分。使用您自己的 事件 包装器并根据您的需求进行定制。

LiveData 是如何通信的?

就一句话,UI层注册好一个 observer,就存储到一个存储着观察者的 map 中,直到开发者调用 postValue/setValue 则遍历该 map,触发 observer 的onChanged 通知,在此过程中,都会监听组件的生命周期,并以此来判断所匹配的组件是否处于活动状态,否则直接 return。

PostValue 可以在任意线程中调用,而 SetValue 只能在主线程中,因为PostValue 多了一步切换主线程的操作。

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
        setValue((T) newValue);
    }
};

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    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;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;

    // 敲黑板,划重点
    observer.mObserver.onChanged((T) mData);
}

LiveData 的粘性事件

发送消息 早于 注册事件,注册的 VC 依然能够接收到消息,我们称之为粘性事件。即先调用 LiveDatapostValue/setValue 方法,后注册 observe,依然能够收到 onChange() 的通知。

为什么 LiveData 先发送后注册,也能够收到通知呢?是哪里分发了onChange() ?

原因在于当 LifecycleOwner 改变状态时,观察者会被通知。例如,如果LifecycleOwner 处于 State#STARTED 状态,给定的观察者将收到Event#ON_CREATE、Event#ON_START 事件。

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    ......

    // 核心在这里
    owner.getLifecycle().addObserver(wrapper);
}

// 跟踪到它的实现类里面
public class LifecycleRegistry extends Lifecycle {
......
@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            ✅ 切入点 
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        // dispatchEvent表示将ON_CREATE、ON_START等事件分发给观察者,以达到监听生命周期的作用
       ......
    }
}

void dispatchEvent(LifecycleOwner owner, Event event) {
    State newState = getStateAfter(event);
    mState = min(mState, newState);
    ✅ 切入点
    mLifecycleObserver.onStateChanged(owner, event);
    mState = newState;
}

// 看到mLifecycleObserver.onStateChanged(owner, event)是不是有种熟悉的感觉

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }

    ,,,,,,
       
    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        ✅ 切入点
        activeStateChanged(shouldBeActive());
    }

    ......
}

void activeStateChanged(boolean newActive) {
    if (newActive == mActive) {
        return;
    }
    // immediately set active state, so we'd never dispatch anything to inactive
    // owner
    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);
    }
}

// setValue()中也调用了一句dispatchingValue(null),只不过setValue传入的是null,而现在这里传入了一个this值
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    ......
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            ✅切入点1
            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) {
    ......
    observer.mObserver.onChanged((T) mData);
}

所以 LiveData 的粘性事件,在于 LiveData 只要在注册观察者时,就会触发 LifecycleOwner 的状态改变,并且会将 ON_CREATE, ON_START, ON_RESUME 三种状态分发给观察者,而这就触发了 onChange 的通知。

相关文章

网友评论

      本文标题:Jetpack LiveData

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