Jetpack系列-LiveData使用和源码分析

1 简介和简单使用

1.1 简介

LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData具有生命周期感知能力,意指它遵循其他应用组件(如Activity、Fragment或Service)的生命周期。这种感知能力可确保LiveData仅更新处于活跃生命周期(onStart、onResume)状态的应用组件观察者。LiveData通常和ViewModel相结合使用。

LiveData依赖于Lifecycle,需要使用Lifecycle提供的状态来判断程序的活跃状态。

如果观察者(由Observer类表示)的生命周期处于STARTED或RESUMED状态,则LiveData会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察LiveData对象而注册的非活跃观察者不会收到更改通知。

Google官网:https://developer.android.google.cn/topic/libraries/architecture/livedata?hl=zh_cn

1.2 简单使用

引入依赖,按需所取。

def lifecycle_version = "2.4.1"
def arch_version = "2.1.0"

// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// Lifecycles only (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"

// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"

// Annotation processor
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"

// optional - helpers for implementing LifecycleOwner in a Service
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"

// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"

// optional - ReactiveStreams support for LiveData
implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"

// optional - Test helpers for LiveData
testImplementation "androidx.arch.core:core-testing:$arch_version"

创建一个单例StrLiveData,里边会实例化一个MutableLiveData,用来存储String类型的数据。

object StrLiveData {
    //懒加载
    val info: MutableLiveData by lazy { MutableLiveData() }
}

在Activity中使用。

class LiveDataActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)

        val tvContent = findViewById(R.id.tv_content)

        //观察数据变化,界面可见时,才会给TextView设置数据
        StrLiveData.info.observe(this) {
            tvContent.text = it
        }

        //观察数据变化,不管界面可见不可见,都给TextView设置数据
        //observeForever不会考虑生命周期,任何状态下都会执行
        StrLiveData.info.observeForever {
            tvContent.text = it
        }

        //主线程修改数据
        StrLiveData.info.value = "在主线程修改的数据"

        thread {
            Thread.sleep(2000)
            //子线程修改数据
            StrLiveData.info.postValue("在子线程修改的数据")
        }
    }
}

XML文件。




    


1.3 关系框架

2 源码分析

2.1 setValue 主线程修改数据

首先在业务层单例中实例化了一个MutableLiveData,MutableLiveData继承LiveData,只保留setValue和postValue两个设置数据的方法,简化使用。

public class MutableLiveData extends LiveData {

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

当业务层调用LiveData的setValue方法时,在主线程修改数据。

//主线程修改数据
StrLiveData.info.value = "在主线程修改的数据"

setValue方法首先会检查当前是否是主线程,然后会对mVersion+1,接着分发数据。

@MainThread
protected void setValue(T value) {
    //检查是否是主线程
    assertMainThread("setValue");
    //mVersion+1
    mVersion++;
    mData = value;
    //分发数据
    dispatchingValue(null);
}

mVersion是LiveData粘性数据特性的关键,它的初始值是-1。

static final int START_VERSION = -1;

public LiveData() {
     mData = NOT_SET;
     //LiveData实例化的时候给mVersion赋值为-1
     mVersion = START_VERSION;
}

分发数据的时候有两种情况,一种是调用LiveData.observe(),另一种是调用LiveData.observeForever()。ObserverWrapper是观察者的包装类。

void dispatchingValue(@Nullable ObserverWrapper initiator) {
        ...
        //initiator(观察者)不为空
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            //initiator(观察者)为空,需要遍历所有的观察者
            for (Iterator, ObserverWrapper>> iterator =
                 mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
       ...
}

接下来调用considerNotify方法。然后对当前是否是活跃状态进行检查,也就是mActive是否为true。为true才会继续执行。就这对mVersion进行对比,由于在setValue的时候mVersion++之后变为0,mLastVersion为-1,所以这里observer.mLastVersion >= mVersion不成立,数据会正常分发出去,这就是造成粘性数据特征的原因。

如果调用LiveData.observe(),那么当Lifecycle状态为STARTED和RESUMED,也就是Activity/Fragment生命周期为onStart和onResume的时候,mActive=true,其他状态和生命周期下,mActive=fale;如果调用LiveData.observeForever(),mActive一直为true,这就实现了调用LiveData.observeForever()时候,观察者不会去考虑生命周期和状态,所有数据都会无条件感知。

private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        //判断mActivie是否为true。
        //调用LiveData.observe()时会根据状态和生命周期计算mActive的值;
        //调用LiveData.observeForever()时mActive一直为true。
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //判断mVersion
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //回调数据给观察者
        observer.mObserver.onChanged((T) mData);
}

2.2 postValue 子线程修改数据

当业务层调用LiveData的postValue方法时,在子线程修改数据。

thread {
    ...
    //子线程修改数据
    StrLiveData.info.postValue("在子线程修改的数据")
}

postValue方法中最终也会通过Handler切换到主线程。

protected void postValue(T value) {
    boolean postTask;
    //加锁,防止线程安全问题
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    //切换到主线程
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

在ArchTaskExecutor中,会实例化一个DefaultTaskExecutor,然后调用DefaultTaskExecutor的postToMainThread方法。

private ArchTaskExecutor() {
    mDefaultTaskExecutor = new DefaultTaskExecutor();
    mDelegate = mDefaultTaskExecutor;
}

@Override
public void postToMainThread(Runnable runnable) {
    mDelegate.postToMainThread(runnable);
}

DefaultTaskExecutor使用Handler进行线程间通信,实现子线程到主线程切换。

@Override
public void postToMainThread(Runnable runnable) {
    if (mMainHandler == null) {
        synchronized (mLock) {
            if (mMainHandler == null) {
                mMainHandler = new Handler(Looper.getMainLooper());
            }
        }
    }
    //noinspection ConstantConditions
    mMainHandler.post(runnable);
}

而在postToMainThread中传入的Runnable中,最红也调用了setValue,接下来的逻辑就和主线程中修改数据一致了。

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

2.3 observe 根据生命周期感知数据变化

调用LiveData的observe( LifecycleOwner owner, Observer super T> observer)方法时,传入了一个被观察者和观察者。

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
    //检查是否是主线程
    assertMainThread("observe");
    //获取Lifecycle当前状态,如果是销毁状态,那就忽略,不再继续往下进行
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    //创建一个LifecycleBoundObserver对象,包装了LifecycleOwner和Observer。
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    //ObserverWrapper包装了LifecycleBoundObserver和Observer
    //把Observer和LifecycleBoundObserver存入map
    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);
}

LifecycleBoundObserver是LiveData的内部类,继承了ObserverWrapper,并且实现LifecycleObserver。传入了一个被观察者和观察者。

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() {
        //从Lifecycle获取到当前是否是活跃状态(UI可见状态)。
        //Activity/Fragment生命周期onStart和onResume,Lifecycle对应状态为STARTED和RESUMED时,处于活跃状态。
        //这里使用了一个比较,也就是状态在STARTED和STARTED之后时,就处于活跃状态。
        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;
            //调用ObserverWrapper的activeStateChanged,再调用dispatchingValue分发数据。
            activeStateChanged(shouldBeActive());
            currentState = mOwner.getLifecycle().getCurrentState();
        }
    }

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

    @Override
    void detachObserver() {
        //观察者和被观察者解除绑定
        mOwner.getLifecycle().removeObserver(this);
    }
}

ObserverWrapper是LiveData的抽象内部类。

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;
        changeActiveCounter(mActive ? 1 : -1);
        if (mActive) {
            //处于活跃状态,发送最新的值
            dispatchingValue(this);
        }
    }
}

2.3 observeForever 无条件感知数据变化

在调用LiveData的observeForever方法时,没有传入被观察者,值传入了观察者,这就决定了调用observeForever之后无法根据Activity/Fragment的生命周期去判断合适感知数据,只能无条件的接收所有数据。这里用AlwaysActiveObserver对观察者进行了包装。

@MainThread
public void observeForever(@NonNull Observer super T> observer) {
    //判断是否是主线程
    assertMainThread("observeForever");
    //创建一个AlwaysActiveObserver对象,对Observer进行包装
    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
    //ObserverWrapper包装了AlwaysActiveObserver和Observer
    //把Observer和AlwaysActiveObserver存入map
    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;
    }
    //这里传入的mActive一直是true,所以消息一直能无条件回调给观察者
    wrapper.activeStateChanged(true);
}

再看AlwaysActiveObserver,shouldBeActive固定返回true。所以在considerNotify方法中,一直能执行到observer.mObserver.onChanged((T) mData),把数据回调给观察者。

private class AlwaysActiveObserver extends ObserverWrapper {

    AlwaysActiveObserver(Observer super T> observer) {
        super(observer);
    }

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

3 流程图

根据上边的源码分析,画出以下流程图。

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/19450,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?