二、Jetpack源码解析(LiveData)

一、前言

LiveData是一个基于观察者模式、具生命感知能力的数据包装类。

从这句话中,我们可以知道它拥有2个特点:

  • 1、采用观察者模式。
  • 2、拥有生命感知能力。

正是这2个特点,赋予了它不平凡的能力:

1、当LiveDate数据改变时,只会通知当前处于活跃状态的观察者。 2、当观察者从非活跃状态恢复到活跃状态时,并且在此期间,LiveDate数据有更新,也会收到数据更新的通知。 3、当生命周期处于Destroy时,自动解绑所有的观察者。

注意:

LiveData不适合作为事件Event。如:保存用户数据类,对用户是否登录进行响应。 不正确的使用方式,会导致内存泄漏。如:将Activity的生命周期,传入PupupWindow,并在其中进行响应。

二、LiveData源码解析

LiveData是一个没有抽象构造方法的抽象类,它主要有两个子类:MutableLiveData和MediatorLiveData,后续我会一一讲解。 我们先看LiveData的构造函数:

java 复制代码
    public LiveData(T value) {
        mData = value;
        mVersion = START_VERSION + 1;
    }

    public LiveData() {
        mData = NOT_SET;
        mVersion = START_VERSION;
    }

这里为LiveData中设置初始值,其中mVersion是一个同步标志位,用于LiveData数据分发,确保该LiveData每次更新数据,不会重复和缺失提示所有观察者。

其次看observe方法

java 复制代码
    @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);
    }

LifcycleOwner表示生命周期拥有者,即Activity或Fragment,后续我们称之为宿主。 1、先判断observe方法的调用是否在主线程,否则会抛异常。 2、首先判断宿主生命周期是否处于Destroy状态,不是才继续执行。 3、创建一个LifecycleBoundObserver的wrapper对象,其作用是将LiveData Observer转换成Lifecycle Observer,用以感知生命周期的变化。 4、将wrapper对象添加到mObservers中。

java 复制代码
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;

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

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

这样需要注意的是,传入的key是observer对象,并判断existing.isAttachedTo(owner),这意味着:

1、同一个observer对象,不能多次使用不同的生命周期同一个LiveData中进行注册。如:

kotlin 复制代码
class TestFragment: Fragment() {
    val liveData = MutableLiveData<Int>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        liveData.observe(this){ printlin("lifecycleOwner $it") }
        liveData.observe(viewLifecycleOwner){ printlin("viewLifecycleOwner $it") }
    }
}

2、一个observer可以在多个LiveData中注册,但我们通常不会这样做。 3、一个LiveData可以注册多个observer,比如页面上有多个控件使用同一份数据。

5、最后对wrapper对象添加Lifecycle生命周期监听。

到这里,LiveData和Observer就与生命周期关联起来了。接下来就只需要考虑以下2种情况:

  • 1、LiveData数据改变,如何通知到Observer。
  • 2、生命周期改变,如何通知到Observer。

2.1、LiveData数据改变

LiveData数据改变方式无非2种,setValue()postValue(),代码如下:

java 复制代码
public abstract class LiveData<T> {
    volatile Object mPendingData = NOT_SET;
    private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

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

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

可以看到,其实postValue()最终也是调用到setValue()里。ps:这里postValue()逻辑还是写的挺巧妙的,值得借鉴。 setValue()方法中代码逻辑很简单:

  • 1、检查是否是主线程
  • 2、mVersion同步标志位+1
  • 3、数据赋值
  • 4、调用dispatchingValue,开始发送通知。
ini 复制代码
public abstract class LiveData<T> {
    ......
    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;
    }
    ......
}

dispatchingValue()方法需要传入一个ObserverWrapper对象,当其不为null时,表示此次更新只通知该Observer;否则,表示通知所有Observer。这里我们传入的是null,即将mObservers中所有的ObserverWrapper对象依次传入considerNotify方法中。 dispatchingValue()方法内部也做了异步处理流程,当我们调用到dispatchingValue()时,如果上一次dispatchingValue()还没执行完毕,即mDispatchingValue为true,就会将mDispatchInvalidated设置为true,表示正在更新的数据无效,并直接返回。而上一次还在dispatchingValue()中执行的代码,会被中断,并重写执行considerNotify更新操作。 虽然目前dispatchingValue()方法都是主线程中进行调用,不存在异步执行的可能,但是该方法不是private的,即有可能够被子类调用,所以还不知Google的如此设计的用意。

java 复制代码
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);
}

considerNotify()方法中代码流程:

  • 1、先判断observer是否处于活跃状态,如果不是则直接退出。
  • 2、此时observer一定处于活跃状态,但宿主有可能处于非活跃状态(可能宿主的状态更新事件还没来)。 如果是这样,observer.shouldBeActive()将返回false,就会调用observer.activeStateChanged(false),将observer的状态变为非活跃状态。并结束执行流程。
  • 3、最后判断observer.mLastVersion >= mVersion,用于避免多次调用通知操作,如果同步标志为验证通过,更新标志位,最终调用到observer.mObserver的onChanged()方法,即我们最开始给LiveData添加的Observer对象的onChanged()回调中。

2.2、生命周期改变

当生命周期发生改变时,Lifecycle会回调到LifecycleBoundObserver的onStateChanged方法中。

java 复制代码
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    ......
    @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();
        }
    }
    ......
}

如果Observer所对应的宿主的生命周期是否已处于DESTROYED状态,则让该Observer取消对LiveData事件订阅,并直接返回。否则调用activeStateChanged(),改变Observer的激活状态。

java 复制代码
private abstract class ObserverWrapper {
    ......
    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        mActive = newActive;
        changeActiveCounter(mActive ? 1 : -1);
        if (mActive) {
            dispatchingValue(this);
        }
    }
}

当Observer对象活跃时,调用changeActiveCounter(1),让活跃的对象+1,并调用dispatchingValue(this)方法,通知自身数据更新。这里我们可以看到:当宿主生命周期从非活跃状态变成活跃状态时,Observer对象会收到LiveData最新的数据更新通知。 当Observer对象不活跃时,调用changeActiveCounter(-1),让活跃的对象-1。

java 复制代码
public abstract class LiveData<T> {
    @MainThread
    void changeActiveCounter(int change) {
        int previousActiveCount = mActiveCount;
        mActiveCount += change;
        if (mChangingActiveState) {
            return;
        }
        mChangingActiveState = true;
        try {
            while (previousActiveCount != mActiveCount) {
                boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
                boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
                previousActiveCount = mActiveCount;
                if (needToCallActive) {
                    onActive();
                } else if (needToCallInactive) {
                    onInactive();
                }
            }
        } finally {
            mChangingActiveState = false;
        }
    }

changeActiveCounter方法主要为了改变mActiveCount数量,并发出LiveData的活跃状态回调:

  • 1、当LiveData的活跃Observer个数由0变成大于0时,调用onActive()。
  • 2、当LiveData的活跃Observer个数由大于0变成0时,调用onInactive()。

注意:不是第一次活跃Observer个数由0变成大于0时,才调用onActive(),而是每次都会。onInactive()也是一样

2.3、observeForever

开头也说了,LiveData是一个基于观察者模式、具生命感知能力的数据包装类。那如果我们只是个普通的类,并没有Lifecycle对象,数据的释放都需要手动执行,那LiveData就没法用了啊!

别担心,Google早就考虑到了,他们给LiveData添加了有个observeForever方法,该方法完全脱离生命周期的管理,也就意味着这个方法注册的Observer对象需要手动注销。

java 复制代码
public abstract class LiveData<T> {
    .......
    @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;
        }
        wrapper.activeStateChanged(true);
    }

    @MainThread
    public void removeObserver(@NonNull final Observer<? super T> observer) {
        assertMainThread("removeObserver");
        ObserverWrapper removed = mObservers.remove(observer);
        if (removed == null) {
            return;
        }
        removed.detachObserver();
        removed.activeStateChanged(false);
    }
    .....
}

这个流程跟observe(LifecycleOwner owner, Observer<? super T> observer)方法很像,只不过它不需要LifecycleOwner对象。并且方法内,并没有用LifecycleBoundObserver类,而是用的AlwaysActiveObserver类,这两个类都继承至ObserverWrapper

scala 复制代码
private class AlwaysActiveObserver extends ObserverWrapper {
    AlwaysActiveObserver(Observer<? super T> observer) {
        super(observer);
    }

    @Override
    boolean shouldBeActive() {
        return true;
    }
}

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @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 shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }
    ......
}

这个类很简单,相比于LifecycleBoundObserver,它没有实现LifecycleEventObserver接口,即感知不到生命周期回调,也就不能自动解绑。 同时shouldBeActive()方法总是返回true,表示在任何情况下,该Observer都处于活跃状态。也就是说,只要LiveData数据有更新,那通过observeForever()添加的Observer都会收到通知。

三、MutableLiveData源码解析

MutableLiveData源码很简单,只是暴露父类LiveData的postValuesetValue方法。

java 复制代码
public class MutableLiveData<T> extends LiveData<T> {
    public MutableLiveData(T value) {
        super(value);
    }

    public MutableLiveData() {
        super();
    }

    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

四、MediatorLiveData源码解析

MediatorLiveData可以通过addSource,监听多个LiveData数据源的变化,并对这些数据源发生变化时进行响应,转化成MediatorLiveData的变化。

java 复制代码
public class MediatorLiveData<T> extends MutableLiveData<T> {
    private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();

    @MainThread
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
        Source<S> e = new Source<>(source, onChanged);
        Source<?> existing = mSources.putIfAbsent(source, e);
        if (existing != null && existing.mObserver != onChanged) {
            throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        }
        if (existing != null) {
            return;
        }
        if (hasActiveObservers()) {
            e.plug();
        }
    }

    @MainThread
    public <S> void removeSource(@NonNull LiveData<S> toRemote) {
        Source<?> source = mSources.remove(toRemote);
        if (source != null) {
            source.unplug();
        }
    }

    @CallSuper
    @Override
    protected void onActive() {
        for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
            source.getValue().plug();
        }
    }

    @CallSuper
    @Override
    protected void onInactive() {
        for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
            source.getValue().unplug();
        }
    }
}

MediatorLiveData也比较简单

  • 1、addSource方法中,将数据源LiveDataObserver包装成Source对象,并存入mSources中,如果MediatorLiveData的有处于激活的Observer,则调用Source的plug()方法,Source对象将永久订阅数据源LiveData
  • 2、removeSource方法中,从mSources中移除Source对象,并调用Source的unplug()方法,让Source对象注销对数据源LiveData的永久订阅。
  • 3、当LiveData执行onActive()时,会调用所有Source的plug()方法。
  • 4、当LiveData执行onInactive()时,会调用所有Source的unplug()方法。

这意味着:当MediatorLiveData处于活跃状态时,如果数据源LiveData数据改变,都会回调到Source对象中。反之,而如果处于非活跃状态时,就不会回调到Source对象中。

java 复制代码
private static class Source<V> implements Observer<V> {
    final LiveData<V> mLiveData;
    final Observer<? super V> mObserver;
    int mVersion = START_VERSION;

    Source(LiveData<V> liveData, final Observer<? super V> observer) {
        mLiveData = liveData;
        mObserver = observer;
    }

    void plug() {
        mLiveData.observeForever(this);
    }

    void unplug() {
        mLiveData.removeObserver(this);
    }

    @Override
    public void onChanged(@Nullable V v) {
        if (mVersion != mLiveData.getVersion()) {
            mVersion = mLiveData.getVersion();
            mObserver.onChanged(v);
        }
    }
}

其实从代码层面看,源LiveData并没有observeMediatorLiveData中,MediatorLiveData只是为源LiveData提供一个统一的生命周期环境。 使用MediatorLiveData需要注意的地方:

如果一个MediatorLiveData添加了A、B两个源LiveData,且对应的Observer都会给MediatorLiveData赋值。 当inActive时,A、B两个源LiveData都发生数据改变,则Active后,MediatorLiveData只会响应最后一次添加的源LiveData的数据变化。

java 复制代码
public class MainActivity extends AppCompatActivity {
    private MediatorLiveData<Integer> liveData = new MediatorLiveData<>();
    private LiveData<Integer> sourceA = new MutableLiveData<>();
    private LiveData<Integer> sourceB = new MutableLiveData<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        liveData.addSource(sourceA, integer -> liveData.setValue(integer));
        liveData.addSource(sourceB, integer -> liveData.setValue(integer));
        liveData.observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                Toast.makeText(MainActivity.this, "result: " + integer, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

五、高级用法

5.1、Transformations.map

LiveData的数据,不会通知inActive的观察者,但是当观察者恢复到active后,会得到最新的data数据更新。

kotlin 复制代码
@MainThread
@NonNull
public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source, @NonNull final Function<X, Y> func) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        @Override
        public void onChanged(@Nullable X x) {
            result.setValue(func.apply(x));
        }
    });
    return result;
}

5.2、Transformations.switchMap

用于多数据源的切换和控制

java 复制代码
@MainThread
@NonNull
public static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> source, @NonNull final Function<X, LiveData<Y>> switchMapFunction) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        LiveData<Y> mSource;

        @Override
        public void onChanged(@Nullable X x) {
            LiveData<Y> newLiveData = switchMapFunction.apply(x);
            if (mSource == newLiveData) {
                return;
            }
            if (mSource != null) {
                result.removeSource(mSource);
            }
            mSource = newLiveData;
            if (mSource != null) {
                result.addSource(mSource, new Observer<Y>() {
                    @Override
                    public void onChanged(@Nullable Y y) {
                        result.setValue(y);
                    }
                });
            }
        }
    });
    return result;
}

5.3、Transformations.distinctUntilChanged

普通LiveData,只要调用setValue,都会回调到Observer(激活状态下)。 而提供distinctUntilChanged方法,只有数据在变化时,才会回调到Observer中。

java 复制代码
@MainThread
@NonNull
public static <X> LiveData<X> distinctUntilChanged(@NonNull LiveData<X> source) {
    final MediatorLiveData<X> outputLiveData = new MediatorLiveData<>();
    outputLiveData.addSource(source, new Observer<X>() {

        boolean mFirstTime = true;

        @Override
        public void onChanged(X currentValue) {
            final X previousValue = outputLiveData.getValue();
            if (mFirstTime
                    || (previousValue == null && currentValue != null)
                    || (previousValue != null && !previousValue.equals(currentValue))) {
                mFirstTime = false;
                outputLiveData.setValue(currentValue);
            }
        }
    });
    return outputLiveData;
}
相关推荐
alexhilton3 天前
选择Retrofit还是Ktor:给Android开发者的指南
android·kotlin·android jetpack
用户67958126582093 天前
compositionLocalOf和staticCompositionLocalOf,你都用对了吗
android jetpack
方之长6 天前
我写了个App,上架 Google Play 一年,下载不到 10 次,于是决定把它开源了
android·github·android jetpack
我命由我123456 天前
Android Studio - Android Studio 查看项目的 Android SDK 版本(4 种方式)
android·java·ide·java-ee·android studio·android jetpack·android runtime
工程师老罗15 天前
我用Ai学Android Jetpack Compose之CircularProgressIndicator
android·android jetpack
工程师老罗15 天前
我用Ai学Android Jetpack Compose之Icon
android·android jetpack
工程师老罗15 天前
我用Ai学Android Jetpack Compose之Row
android·android jetpack
砖厂小工16 天前
AI 也能"看懂"图片: Android AI 搜图的奥秘
openai·android jetpack
普通网友1 个月前
Android-Jetpack架构组件(一)带你了解Android-Jetpack
jvm·架构·android jetpack
2401_897915651 个月前
Android Jetpack 之 Paging3的一些踩坑记录
android·android jetpack