LiveData原理解析

什么是LiveData

LiveDataAndroid Architecture Components 其中的一个组件。主要用于更新UI数据和组件之间传值。

1、LiveData是一种持有可被观察数据的类。它通过观察者模式实现了数据变化的动态通知,即当观察者生命周期处于活跃状态时,能够感知数据的变化。

2、能够感知生命周期,内部通过Lifecycle来感知生命周期,在Activity、Fragment、Service中当对应生命周期为Destroy的时候,会销毁观察者,避免内存泄露;

LiveData的简单使用

LiveData的使用十分方便,只需要简单的三步:

1、创建LiveData对象,LiveData是抽象类,所以需要创建它的子类MutableLiveData

2、设置观察者observe,第一个参数是LifecycleOwner对象,第二个是观察者监听,当数据改变的时候会在onChanged方法内做出响应;

3、设置数据,通过postValue或者setValue方法来更新数据;

public class MainActivity extends AppCompatActivity {
    private MutableLiveData liveData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 1.创建LiveData对象 
        liveData = new MutableLiveData();
        // 2.添加观察者
        liveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                // 提示数据变化
                Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
            }
        });
        findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 3.改变数据
                liveData.postValue("测试");
            }
        });
    }

}

LiveData原理

一、LiveData是如何实现观察者订阅,并发送事件的?

LiveData通过observe和observeForever来订阅观察者,查看源码可以看到

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    ///1、判断当前状态是否是DESTROYED,如果不是则添加观察者
    if (owner.getLifecycle().getCurrentState() != State.DESTROYED) {
        ///2、创建LifecycleBoundObserver类
        LiveData<T>.LifecycleBoundObserver wrapper = new LiveData.LifecycleBoundObserver(owner, observer);
        ///3、将观察者和LifecycleOwner添加到map中一一对应
        LiveData<T>.ObserverWrapper existing = (LiveData.ObserverWrapper)this.mObservers.putIfAbsent(observer, wrapper);
        // 对应观察者只能与一个owner绑定
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer with different lifecycles");
        } else if (existing == null) {
            // 当不存在的时候添加LifecycleObserver
            owner.getLifecycle().addObserver(wrapper);
        }
    }
}

1、源码首先判断当前状态是否是DESTROYED,如果不是则不会注册当前;

2、创建LifecycleBoundObserver类,该类实现了生命周期与观察者的绑定,在此类中有个onStateChanged方法如下,onStateChanged方法中会在生命周期状态发生改变时判断当前状态是否是DESTROYED,如果是就移除当前监听者,避免内存泄露。

public void onStateChanged(LifecycleOwner source, Event event) {
    // 当生命周期处于DESTROYED的时候移除当前订阅者
    if (this.mOwner.getLifecycle().getCurrentState() == State.DESTROYED) {
        LiveData.this.removeObserver(this.mObserver);
    } else {
        // 非DESTROYED的时候进行状态改变
        this.activeStateChanged(this.shouldBeActive());
    }
}

LifecycleBoundObserver类继承ObserverWrapper类,ObserverWrapper又是观察者的包装类。

LifecycleBoundObserver类通过实现了GenericLifecycleObserver接口->LifecycleEventObserver接口,最终实现了LifecycleEventObserver接口,所以下面将wrapper添加到Lifecycle的监听中。

owner.getLifecycle().addObserver(wrapper);

3、LiveData中创建了一个Map来存储每一个观察者和生命周期的包装类,并且会判断当前对应观察者只能与一个owner绑定。

二、postValue和setValue过程分析

LiveData可以通过postValue和setValue来设置数据,当请求完网络数据的时候,就可以调用postValue或setValue来设置数据,当然postValue是可以在任意线程进行调用,setValue只能在主线程调用。postValue最终也是调用setValue方法。

下面分析一下postValue的源码执行过程:

MutableLiveData类中的postValue和setValue都是调用了父类(LiveData)的方法。直接查看LiveData的postValue方法:

protected void postValue(T value) {
    boolean postTask;
    synchronized(this.mDataLock) {
        postTask = this.mPendingData == NOT_SET;
        this.mPendingData = value;
    }

    if (postTask) {
        // 转到主线程去执行,所以postValue方法可以在任意线程执行
        ArchTaskExecutor.getInstance().postToMainThread(this.mPostValueRunnable);
    }
}

源码中最终会转到主线程去执行,所以postValue方法可以在任意线程执行,再查看mPostValueRunnable源码:

public LiveData() {
    this.mData = NOT_SET;
    this.mPendingData = NOT_SET;
    this.mVersion = -1;
    this.mPostValueRunnable = new Runnable() {
        public void run() {
            Object newValue;
            synchronized(LiveData.this.mDataLock) {
                newValue = LiveData.this.mPendingData;
                LiveData.this.mPendingData = LiveData.NOT_SET;
            }
			// 这里最终调用了setValue方法
            LiveData.this.setValue(newValue);
        }
    };
}

在LiveData的构造方法中创建了mPostValueRunnable,并在最后调用了setValue方法。下面再看一下setValue方法:

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    // 版本+1
    ++this.mVersion;
    // 将值赋值给全局变量mData
    this.mData = value;
    // 分发数据
    this.dispatchingValue((LiveData.ObserverWrapper)null);
}

setValue中主要做了三个事:

1、版本+1,LiveData的mVersion变量表示的是发送数据的版本,每次发送一次数据, 它都会+1;

2、将值赋值给全局变量mData;

3、调用dispatchingValue方法分发数据,dispatchingValue方法中主要调用的是considerNotify方法

private void considerNotify(LiveData<T>.ObserverWrapper observer) {
    // 如果观察者处于活跃状态
    if (observer.mActive) {
        // 判断是否应该改变状态
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
        } else if (observer.mLastVersion < this.mVersion) {// 当观察者的最后版本小于当前版本,表示有数据改变了
            // 将当前版本跟观察者的版本进行统一
            observer.mLastVersion = this.mVersion;
            // 触发onChange方法
            observer.mObserver.onChanged(this.mData);
        }
    }
}

查看shouldBeActive方法,这里通过LifeCycle的当前状态对比State.STARTED来判断,当是STARTED或者RESUMED状态时,才会触发observer的activeStateChanged方法,这时就会执行LifecycleBoundObserver中的activeStateChanged方法。

boolean shouldBeActive() {
    return this.mOwner.getLifecycle().getCurrentState().isAtLeast(State.STARTED);
}

另外,当observer的mLastVersion(初始值为-1)版本小于LiveData的mVersion时,就表示有新数据改变了,所以就会触发onChanged方法。

三、observe和observeForever区别

observer会自动监听生命周期,当是STARTED和RESUMED的时候才会触发订阅,而observeForever则是会一直检测数据变化,只要数据变化了就会触发订阅。

@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
    assertMainThread("observeForever");
    // 会创建一个总是活动的观察者
    LiveData<T>.AlwaysActiveObserver wrapper = new LiveData.AlwaysActiveObserver(observer);
	......
}

如源码所示,observeForever会创建一个总是活动的观察者AlwaysActiveObserver,改类继承ObserverWrapper,并实现了shouldBeActive方法,而且始终返回true,所以只要数据一改变,会触发onChanged方法。

private class AlwaysActiveObserver extends LiveData<T>.ObserverWrapper {
    AlwaysActiveObserver(Observer<? super T> observer) {
        super(observer);
    }
	// 一直返回true
    boolean shouldBeActive() {
        return true;
    }
}

而在LifecycleBoundObserver中实现了onStateChanged方法,在该方法中会根据当前状态是否为State.DESTROYED来自动移除监听者,所以observeForever则不会,所以需要在onDestroy中手动移除。

@Override
protected void onDestroy() {
    super.onDestroy();
    // 使用observeForever需要手动移除
    liveData.removeObserver(MyObserver);
}

四、LiveData粘性事件和数据倒灌

粘性事件:先setValue/postValue,后调用observe(),如果成功收到了回调,即为粘性事件。

数据倒灌:先setValue/postValue,后调用observe(new Obs()),至此收到了回调。然后再第二次调用observe(new anotherObs()),如果还能收到第一次的回调,则为“数据倒灌”。

大家可以看一下这篇文章:

关于LiveData粘性事件所带来问题的解决方案

组件之间传值工具类:

UnPeek-LiveData

LiveDataBus

你可能感兴趣的:(Android,Jetpack,android,LiveData)