二、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;
}
相关推荐
一航jason11 天前
Android Jetpack Compose 现有Java老项目集成使用compose开发
android·java·android jetpack
帅次12 天前
Android CoordinatorLayout:打造高效交互界面的利器
android·gradle·android studio·rxjava·android jetpack·androidx·appcompat
IAM四十二15 天前
Jetpack Compose State 你用对了吗?
android·android jetpack·composer
Wgllss16 天前
那些大厂架构师是怎样封装网络请求的?
android·架构·android jetpack
x0241 个月前
Android Room(SQLite) too many SQL variables异常
sqlite·安卓·android jetpack·1024程序员节
alexhilton1 个月前
深入理解观察者模式
android·kotlin·android jetpack
Wgllss1 个月前
花式高阶:插件化之Dex文件的高阶用法,极少人知道的秘密
android·性能优化·android jetpack
上官阳阳1 个月前
使用Compose创造有趣的动画:使用Compose共享元素
android·android jetpack
沐言人生1 个月前
Android10 Framework—Init进程-15.属性变化控制Service
android·android studio·android jetpack
IAM四十二1 个月前
Android Jetpack Core
android·android studio·android jetpack