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

如果有一个观察者的生命周期处于 STARTEDRESUMED 状态,则 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使用和生命感知原理的主要内容,如果未能解决你的问题,请参考以下文章

LiveData原理分析

jetpack-liveData 原理解析

Android mvvm 之 LiveData 的原理

Android开发——LiveData实现原理

Android LiveData原理分析

Jetpack系列 — LiveData