Android--Jetpack--LiveData源码分析

时人不识凌云木,直待凌云始道高

一,基本使用

基本使用请看文章Android--Jetpack--LiveData-CSDN博客

二,MutableLiveData

首先说一下我们为什么要用MutableLiveData呢,来看看LiveData的源码:

public abstract class LiveData<T> {

    。。。。

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

setValue 和postValue 都是protected方法,外面拿不到

同时,这里的setValue使用了注解@MainThread 说明只能在主线程发送数据

再来看看MutableLiveData的源码:

public class MutableLiveData<T> extends LiveData<T> {

    /**
     * Creates a MutableLiveData initialized with the given {@code value}.
     *
     * @param value initial value
     */
    public MutableLiveData(T value) {
        super(value);
    }

    /**
     * Creates a MutableLiveData with no value assigned to it.
     */
    public MutableLiveData() {
        super();
    }

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

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

这是它的全部代码,只是把postValue和setValue这两个方法公开了。其余的都是继承LiveData。

这就是我们为什么使用MutableLiveData的原因。

三,消息发送源码分析

setValue和postValue都是发送数据的,但是setValue只能在主线程发送数据,而postValue却不受线程限制。

我们来看看postValue的源码:

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

通过ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);切换到了主线程,再来看看mPostValueRunnable:

private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};

最终还是调用了setValue,所以说postValue只是多了一个线程切换的操作。

所以我们重点看下setValue的源码:

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

首先看看assertMainThread("setValue"):

static void assertMainThread(String methodName) {
    if (!ArchTaskExecutor.getInstance().isMainThread()) {
        throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                + " thread");
    }
}

这个方法的作用就是检查是不是在主线程,不在主线程就抛异常。

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

上面都是判断,主要来看这行代码:

for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
    considerNotify(iterator.next().getValue());
    if (mDispatchInvalidated) {
        break;
    }
}

这里有个mObservers,我们来看看这是什么:

private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
        new SafeIterableMap<>();

这是一个key为Obsercer,value为ObserverWrapper的map集合。

我们再来看看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);
}

是在observe方法中添加的,先看看observe什么时候调用:

Observer observer =new Observer<String>() {
    @Override
    public void onChanged(String o) {
        System.out.println("yz---"+o);
        txt.setText(o);
    }
};
//获取viewmodule
model =new ViewModelProvider(this).get(MyViewModel.class);
model.getCount().observe(this,observer);

在上篇使用的时候,我们会在Activity中这样调用observe,第一个参数是Activity,第二个参数是自己定义的观察者。

然后我们再回到observe方法中,首先检查了是不是在主线程,然后判断如果当前Activity的状态是不可用状态,就返回。如果是可用状态,就将Activity和观察者包装成wrapper,并且以观察者为key,wrapper为value添加进mObservers集合。如果这个集合里面不是空的并且不是重复的observer 就执行owner.getLifecycle().addObserver(wrapper);我们在Android--Jetpack--Lifecycle详解-CSDN博客Android--Jetpack--Lifecycle详解-CSDN博客Android--Jetpack--Lifecycle详解-CSDN博客中讲过,这个就会添加进观察者集合中。

了解了mObservers之后,我们再回到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;
}

这里会执行considerNotify(iterator.next().getValue());继续看它的源码:

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

将上面我们包装的ObserverWrapper传了进来。

首先判断这个观察者是不激活状态,就返回不执行

然后就到了这句代码:

if (observer.mLastVersion >= mVersion) {
    return;
}

mVersion刚才出现过,我们看看mVersion:

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

在我们创建new MutableLiveData<>()的时候,会给mVersion赋值START_VERSION=-1

然后我们setValue的时候mVersion会+1.

之后就会走到considerNotify(iterator.next().getValue())方法中。

observer.mLastVersion的初始值:

static final int START_VERSION = -1;
int mLastVersion = START_VERSION;

所以,我们setValue的时候,会走到dispatchingValue方法中,然后会走到considerNotify中,接下来就到了 observer.mObserver.onChanged((T) mData)方法,这时就会回调observer的api把消息发送出来了。

四,数据倒灌和粘性问题

正常我们的执行顺序是:new LiveData-->绑定observer-->setValue执行onChanged

但是当我们跨Activity的时候,可能执行顺序是这样的:

new LiveData-->setValue执行onChanged-->绑定observer

这样会有什么问题呢?

首先,正常的执行流程上面我们已经分析过了。

下面 我们来看看不正常的流程:

new LiveData的时候:

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

mVersion=-1

然后执行setValue:

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

mVersion =0

这时不会走到:

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

因为还没绑定observer:

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

所以此时observer.mLastVersion =-1

但是因为是一个while循环,所以当绑定observer时,然后会走到:

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

然后我们就会收到消息。

所以就造成了我们订阅之前的消息也收到了。

五,解决方案

public class MyLiveData<T> extends MutableLiveData<T> {
    private int mVersion = 0;//被观察者的版本
    private int observerVersion = 0;//观察者的版本

    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //每次订阅的时候,先把版本同步
        observerVersion = mVersion;
        super.observe(owner, new Observer<T>() {
            @Override
            public void onChanged(T t) {
                if (mVersion != observerVersion) {
                    observer.onChanged(t);
                }
            }
        });
    }

    @MainThread
    public void setValue(T value) {
        mVersion++;
        super.setValue(value);

    }

}

相关推荐

  1. Android--Jetpack--LiveData分析

    2023-12-10 11:30:04       39 阅读
  2. LiveData和ViewModel学习

    2023-12-10 11:30:04       15 阅读
  3. Kotlin: JetpackLiveData简单应用

    2023-12-10 11:30:04       52 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-10 11:30:04       17 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-10 11:30:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-10 11:30:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-10 11:30:04       18 阅读

热门阅读

  1. 安全扫描五项简介

    2023-12-10 11:30:04       33 阅读
  2. 【原创】录剪视频的折腾之路

    2023-12-10 11:30:04       27 阅读
  3. DevOps - Spug 自动化运维平台

    2023-12-10 11:30:04       36 阅读
  4. Liunx的LVM与磁盘配额

    2023-12-10 11:30:04       40 阅读
  5. Python中函数详解

    2023-12-10 11:30:04       30 阅读
  6. nginx常用笔记备忘

    2023-12-10 11:30:04       30 阅读
  7. cv2.error: OpenCV(4.7.0)

    2023-12-10 11:30:04       38 阅读