LiveData使用和生命感知原理
Posted 一代小强
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LiveData使用和生命感知原理相关的知识,希望对你有一定的参考价值。
你知道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使用和生命感知原理的主要内容,如果未能解决你的问题,请参考以下文章