你知道LiveData是如何做到感知生命周期的吗?
前言
使用LiveData有以下优势
- 数据及时刷新:无论前台任务还是后台任务,只要当前页面处于活跃状态,就能马上刷新数据
- 不会因 Activity 停止而导致崩溃:如果观察者的生命周期处于非活跃状态,则它不会接收任何 LiveData 事件。
- 共享资源:您可以使用单例模式扩展
LiveData
对象以封装系统服务,以便在应用*享它们。 - 不会发生内存泄漏:观察者会绑定到
Lifecycle
对象,并在其关联的生命周期遭到销毁后进行自我清理。
导入依赖
导入LiveData很简单
需要在项目根路径下的build.gradle文件中添加
allprojects {
repositories {
google()
....
}
}
然后在module下添加依赖即可
dependencies {
def lifecycle_version = "2.3.0"
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
}
如果提示
This project uses AndroidX dependencies, but the 'android.useAndroidX' property is not enabled. Set this property to true in the gradle.properties file and retry.
就在项目的根路径下创建新的文件gradle.properties
然后添加如下配置即可
android.useAndroidX=true
android.enableJetifier=true
LiveData用法
监听值变化
livedata可以单独使用,我们只需要创建一个LiveData对象,并观察其值的变化即可。
class MainActivity : AppCompatActivity() {
lateinit var showText: Button;
var liveData = MutableLiveData<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
showText = findViewById(R.id.showText)
// 传入LifecycleOwner,并观察livedata的值
liveData.observe(this, Observer {
// 显示更新后的值
showText.text = it
})
liveData.value = "init"
}
// 点击回调事件,让Livedata更新值
fun onMainThread(view: View) {
liveData.value = "from main thread "
}
// 子线程更新livedata的值
fun onWorkThread(view: View) {
Thread {
liveData.postValue("from work thread")
}.start()
}
// 模拟后台耗时任务,回到activity重新显示最新的值
override fun onStop() {
super.onStop()
Thread {
Thread.sleep(1000)
liveData.postValue("from back work thread")
}.start()
}
}
扩展LiveData
如果有一个观察者的生命周期处于 STARTED
或 RESUMED
状态,则 LiveData 会认为该观察者处于活跃状态。
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager = StockManager(symbol)
private val listener = { price: BigDecimal ->
value = price
}
// LiveData进入活跃状态
override fun onActive() {
stockManager.requestPriceUpdates(listener)
}
// LiveData进入暂停状态
override fun onInactive() {
stockManager.removeUpdates(listener)
}
}
- 当
LiveData
对象具有活跃观察者时,会调用onActive()
方法。这意味着,您需要从此方法开始观察股价更新。 - 当
LiveData
对象没有任何活跃观察者时,会调用onInactive()
方法。由于没有观察者在监听,因此没有理由与StockManager
服务保持连接。
全局共享
我们可以在多个 Activity、Fragment 和 Service 之间共享LiveData对象。为此可以将 LiveData
类实现为一个单例
class StockLiveData : MutableLiveData<String>() {
companion object {
private const val TAG = "StockLiveData"
// 声明一个单例
private lateinit var instance: StockLiveData
fun get(): StockLiveData {
instance = if (::instance.isInitialized) instance else StockLiveData()
return instance
}
}
override fun onActive() {
super.onActive()
Log.d(TAG, "onActive: ")
}
override fun onInactive() {
super.onInactive()
Log.d(TAG, "onInactive: ")
}
}
然后通过单例注册Observer
class MainActivity : AppCompatActivity() {
lateinit var showText: Button;
companion object {
private const val TAG = "MainActivity"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
showText = findViewById(R.id.showText)
// 传入LifecycleOwner,并观察livedata的值
StockLiveData.get().observe(this, {
// 显示更新后的值
showText.text = it
})
}
}
以上就是livedata的基本用法。
跨线程更新原理
LiveData作为抽象类,我们是不能直接使用的,而MutableLiveData 其实只是Livedata的封装。其setValue与postValue均是调用了LiveData的接口。
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
....
}
LiveData的postValue其实就是做了一件事情,更新mPendingData,切到主线程
public abstract class LiveData<T> {
// 锁对象
final Object mDataLock = new Object();
// 用于标志数据是否被更新
static final Object NOT_SET = new Object();
// 用于临时存储更新后的值
volatile Object mPendingData = NOT_SET;
// 在主线程执行的runnable
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
// 将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
return;
}
// 切到主线程
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
}
可以看出来,postValue最后也是调用了setValue
public abstract class LiveData<T> {
...
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
// 存储最新值
mData = value;
// 将值更新的事件通知观察者
dispatchingValue(null);
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
// 如果正在分发,就直接return
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
// setValue 更新的时候,initiator 为null,暂时忽略
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 又是做啥的呢?
public abstract class LiveData<T> {
...
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
// 观察者处于暂停状态,就忽略掉。等周期回调的时候触发
return;
}
// 校验观察者的状态是否可以活跃,否则更新到睡眠状态
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
// 观察者上次获取到值的版本>= 当前的版本,就忽略,防止多次调用
if (observer.mLastVersion >= mVersion) {
return;
}
// 更新观察者的值版本号,并调用onChanged回调
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
}
到此,一次完整的事件通知就结束了,postValue顺带了setValue的实现,也是代码复用的体现。
现在回过头看看liveData的observe干了啥,想必读者也能猜出来了,就是注册一个观察者
public abstract class LiveData<T> {
...
@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);
}
}
感知周期原理
Lifecycle
在了解Livedata感知周期原理前,需要提一下Jetpack中的Lifecycle组件。
Lifecycle 是一个类,用于存储有关组件(如 Activity 或 Fragment)的生命周期状态的信息,并允许其他对象观察此状态。
组件(activity或者fragment)的周期与states的关系如下图
光看图可能会被比较懵,我们来看看代码
class MainActivity : AppCompatActivity() {
companion object {
private const val TAG = "MainActivity"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var data = LifeCycleListener(this.lifecycle)
// 注册lifecycle的回调
lifecycle.addObserver(data)
}
class LifeCycleListener(private val lifecycle: Lifecycle) : LifecycleObserver {
// 标记对应周期回调的方法
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreate() {
Log.d(TAG, "is onCreate: " + (lifecycle.currentState == Lifecycle.State.CREATED))
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
Log.d(TAG, "is onStart: " + (lifecycle.currentState == Lifecycle.State.STARTED))
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
Log.d(TAG, "is onResume: " + (lifecycle.currentState == Lifecycle.State.RESUMED))
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause() {
Log.d(TAG, "is onPause: " + (lifecycle.currentState == Lifecycle.State.STARTED))
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
Log.d(TAG, "is onStop: " + (lifecycle.currentState == Lifecycle.State.CREATED))
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
Log.d(TAG, "is onDestroy: " + (lifecycle.currentState == Lifecycle.State.DESTROYED))
}
}
}
对应的log如下
但这样需要定义很多方法,有一种更简便的实现
class MainActivity : AppCompatActivity() {
companion object {
private const val TAG = "MainActivity"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 注册lifecycle的回调
lifecycle.addObserver(LifecycleEventObserver())
}
class LifecycleWatcher : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
Log.d(TAG, "onStateChanged: lifecycle ${event.name} state ${event.targetState}")
}
}
}
LiveData正是通过这种方式监听activity的周期。
observe实现
LiveData在注册观察者的时候,创建了一个LifecycleBoundObserver 并注册到Lifecycle中。需要注意的是,一个Observer对应一个LifecycleOwner,
public abstract class LiveData<T> {
...
@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);
}
}
LifecycleBoundObserver是LiveData的内部类
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() {
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;
// 通知State变化
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
....
}
看看ObserverWrapper的activeStateChanged方法
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
void activeStateChanged(boolean newActive) {
// 只有从活跃到暂停,或者暂停到活跃,才往下走
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
// 调用LiveData的更新值流程
dispatchingValue(this);
}
}
}
changeActiveCounter 方法主要保存当前状态,并判断是否要通知活跃变化
void changeActiveCounter(int change) {
int previousActiveCount = mActiveCount;
mActiveCount += change;
if (mChangingActiveState) {
return;
}
mChangingActiveState = true;
try {
while (previousActiveCount != mActiveCount) {
// call Active方法的条件:上次没有处于活跃的观察者(带有lifecycleOwner),并且当前有处于活跃的观察者
boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
// call Inactive方法的条件:上次有处于活跃的观察者(带有lifecycleOwner),并且当前没有处于活跃的观察者
boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
previousActiveCount = mActiveCount;
if (needToCallActive)
// 通知当前处于活跃状态
onActive();
} else if (needToCallInactive) {
// 通知当前处于暂停状态
onInactive();
}
}
} finally {
mChangingActiveState = false;
}
}
小结:LiveData主要通过监听lifecycleOwner的周期,来实现粘性事件
解决内存泄漏原理
LiveData是如何保证不发生内存泄漏的呢?
主要是在周期遭到销毁后进行自我清理,切断观察者与activity等的引用关系
// 生命周期的回调
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
// 目标已被销毁,就移除掉观察者,断开引用关系
removeObserver(mObserver);
return;
}
.....
}
但对于没有注册lifecycleOwer的观察者,LiveData就无法主动移除了
observeForever实现
observeForever的实现与observe有点类似,只是无法感知周期。
@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);
}
而AlwaysActiveObserver的实现也比较简单
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<? super T> observer) {
super(observer);
}
// 永远处于活跃状态
@Override
boolean shouldBeActive() {
return true;
}
}
这也意味着,我们需要手动调用一下removeObserver,防止内存泄漏
class MainActivity : AppCompatActivity() {
var observer = Observer<String> {
Log.d(TAG, "no lifecycle Observer: value => $it")
}
override fun onResume() {
super.onResume()
liveData.observeForever(observer)
}
override fun onStop() {
super.onStop()
liveData.removeObserver(observer)
}
}
合并多个源
如果想同时监听多个数据的变化怎么办?可以使用 MediatorLiveData
用法如下
LiveData liveData1 = new LocalLiveData();
LiveData liveData2 = new RemoteLiveData();
MediatorLiveData liveDataMerger = new MediatorLiveData<>();
liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
后记
知识比较零散,这里做了一个总结
- livedata采用观察者模式,内部通过监听生命周期、版本号方式维护数据,保证能及时、有效的刷新。
- Livedata可以配个viewModel,实现MVVM架构。
- call Active方法的条件:上次没有处于活跃的观察者(带有lifecycleOwner),并且当前有处于活跃的观察者。
- call Inactive方法的条件:上次有处于活跃的观察者(带有lifecycleOwner),并且当前没有处于活跃的观察者。
- LiveData内部通过监听组件周期,自动注销观察者,防止内存泄漏。
- 在跨线程更新数据时,通过volatile和加锁方式来保证数据的一致性。
- 内部使用SafeIterableMap 来维护Observer,可以在迭代Observer的同时将其移除掉。
- 一个Observer对应一个lifecycleOwner,否则将报错。