jetpack系列笔记

jetpack系列笔记

一、 jetpack系列之lifecycle
二、 jetpack系列之LiveData



一、LiveData是什么?

官方给的解释如下:

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

详情请查阅LiveData官方文档

二、使用LiveData有什么优势?

  • 确保界面符合数据状态: LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。
  • 不会发生内存泄漏:观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。
  • 不会因 Activity 停止而导致崩溃:如果观察者的生命周期处于非活跃状态(如返回堆栈中的 activity),它便不会接收任何 LiveData 事件。
  • 不再需要手动处理生命周期:界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
  • 数据始终保持最新状态:如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
  • 适当的配置更改:如果由于配置更改(如设备旋转)而重新创建了 activity 或 fragment,它会立即接收最新的可用数据。
  • 共享资源:您可以使用单例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象。

三、LiveData使用

LiveData一般是在MWWM模型中,配合ViewModel完成的。本节主要记录LiveData的简单使用,会在后续文章中添加jetpack组件的搭配使用。

class LiveDataActivity : AppCompatActivity() {
    val TAG = LiveDataActivity::class.java.simpleName
    companion object {
    	//1.声明一个MutableLiveData
        val liveData = MutableLiveData<String>()
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)

		//2、添加观察者
        liveData.observe(this, object: Observer<String> {
            override fun onChanged(value: String) {
                Log.d(TAG, value)
            }
        })
        //主线程中发送数据
        liveData.value = "main thread: set value"

		//子线程中发送数据
        Thread(kotlinx.coroutines.Runnable {
            liveData.postValue("IO thread: set value")
        }).start()
    }
}

MutableLiveData 是 LiveData的子类,不同的是,MutableLiveData将postValue 和 setValue 通过public修饰,可以公开使用,MutableLiveData可以发送消息,LiveData只能接收消息。

setValue 只能在主线程中发送消息,postValue 可以在子线程中发送消息,当然,也可以在主线程中,最终会将消息发送到主线程中。

三、LiveData实现原理

看一下LiveData观察者注册的过程:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    	//断言在主线程中执行
        assertMainThread("observe");
        //判断了lifecycle的生命周期是否是DESTROYED
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //1、将传递过来的owner,即Activity和observer封装到LifecycleBoundObserver中
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //2、将封装好的wrapper放到mObservers中,mObservers是个存放了ObserverWrapper 的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;
        }
        //3.将wrapper 注册到lifecycle的观察者中
        owner.getLifecycle().addObserver(wrapper);
    }

LifecycleBoundObserver 实现了LifecycleEventObserver的接口, LifecycleEventObserver实现了LifecycleObserver接口,通过上一章我们可以知道实现LifecycleObserver接口,就可以注册到lifecycle的观察者中。第三步的注册过程也在lifecycle注册观察者时候分析过。至此,就将observer注册到了lifecycle中,从而有了感知生命周期的能力。
我们看下LifecycleBoundObserver的实现:

	    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;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }
		...
    }

LifecycleBoundObserver 封装了LifecycleOwner,即自己的Activity,并实现了生命周期改变时需要执行的方法。

四、数据的传递过程

数据的传递过程分为两方面,一个是LiveData直接传输数据,一个是当生命周期改变时,执行的操作。

1.首先看一下通过LiveData的setValue时,观察者是怎么接收到数据的。

postValue最终也是在主线程中调用了setValue,我们直接看setValue的实现:

  //LiveData.java
  @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

首先将LiveData的版本mVersion加1,mVersion初始化为-1。mVersion控制了当前发送数据的版本。然后把最新发送的数据保存到mData中,等待分发。

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            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;
    }

在分发的过程中,会遍历mObservers所有的观察者进行分发。这里逻辑比较复杂,用mDispatchInvalidated和mDispatchingValue两个bool型变量和do…while…进行控制。它的主要逻辑是:

  1. 如果只发送一次数据,mDispatchingValue初始为false,会被赋值成true,执行do…while循环,将mDispatchInvalidated 设置成false,遍历整个mObservers中的观察者,继续进行数据发送操作。因为mDispatchInvalidated 为false,do…while循环只进行一次即结束,将mDispatchingValue 置为false;
  2. 如果发送了一次数据,在这个过程中数据并没有发送到所有的观察者的时候,又进行了第二次setValue操作,这个时候,mDispatchingValue是ture,所以mDispatchInvalidated会被置为true,此次调用结束。但是第一次发送数据调用该函数的,依然在do…while…循环中跑,这时mDispatchInvalidated已经为true,for循环被break,剩余的观察者将无法接收到第一次发送的数据。但do…while…循环会被再次执行,又会向所有的观察者发送数据。但此时mData 已经更新为第二次发送的数据,故所有的观察者都将会收到新的数据。

下面是分发的过程:

    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
        //
        // we still first check observer.active to keep it as the entrance for events. So even if
        // the observer moved to an active state, if we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }
  1. 判断observer是激活状态
  2. 判断observer.shouldBeActive()。这里可以看到,只有状态至少是STARTED的时候,才会通知观察者数据改变。
  3. 判断当前观察者记录的数据版本,如果比当前数据的版本号大,说明不需要通知观察者。
  4. 将观察者的版本赋值成当前LiveData的数据版本,并执行观察者的onChanged方法。

2.Activity生命周期改变时,通知观察者

当Activity生命周期发生改变时,也会通知观察者,这被称为LiveData的粘性事件。我们看一下整个逻辑。在Activity生命周期发生的过程已经看过。当走ObserverWithState的dispatchEvent方法分发事件时,由于ObserverWithState中的lifecycleObserver 是LifecycleBoundObserver,我们看一下LifecycleBoundObserver 的onStateChanged方法:

	    @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;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }
  1. 如果当前lifecycle的State 为DESTROYED,会将这个观察者进行移除,所以我们不用手动移除观察者。
  2. 如果上一个的状态和当前状态不一样,则会执行ObserverWrapper的activeStateChanged方法,上文已经进行了分析。

五、LiveData的observeForever

LiveData还有一个observeForever,顾名思义,就是不根据生命周期,一直可以接收到数据,它的使用方式如下:

        liveData.observeForever(object : Observer<String> {
            override fun onChanged(value: String) {
                Log.d(TAG,"receive liveData for ever : $value")
            }
        })

我们看一下它的源码实现:

    @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;
        }
        //直接分发数据,参数固定位true。
        wrapper.activeStateChanged(true);
    }
    
    private class AlwaysActiveObserver extends ObserverWrapper {

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

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

可看到,它是将观察者封装到了AlwaysActiveObserver 中,在这里,shouldBeActive()返回固定为true,说明一直是活跃状态不会区分组件的生命周期。且在创建完AlwaysActiveObserver 后,也会直接去进行数据的分发。

六、屏蔽粘性事件

因为在Activity执行到onStrart()的时候,LiveData如果有数据,就会通知观察者。我们有时候业务中需要屏蔽掉粘性事件。屏蔽粘性事件的方法有很多,这里写一种思路:在注册观察者的时候,将观察者的版本赋值成LiveData的数据版本,这样就不会去通知观察者了。需要用反射的方式去操作:

class NoStickyMutableLiveData<T>: MutableLiveData<T>() {
    private var isCancled = false

    override fun observe(owner:LifecycleOwner, observer:Observer<in T>) {
        super.observe(owner, observer)
		//只修改一次就行
        if (!isCancled) {
            setObserverVersion(observer)
            isCancled = true
        }
    }

    private fun setObserverVersion(observer: Observer<in T>) {
        try {
            //1、获取Observer的mLastVersion
            val liveDataClass = LiveData::class.java
            val mObserversField = liveDataClass.getDeclaredField("mObservers")
            mObserversField.isAccessible = true


            val mObserversObject = mObserversField[this]
            val mObserversClass: Class<*> = mObserversObject.javaClass
            val getMethod = mObserversClass.getDeclaredMethod("get", Any::class.java)
            getMethod.isAccessible = true
            val invokeEntry = getMethod.invoke(mObserversObject, observer)
            var observerWraper: Any? = null
            if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
                observerWraper = invokeEntry.value
            }
            if (observerWraper == null) {
                return
            }
            val superclass: Class<*> = observerWraper.javaClass.superclass
            val mLastVersion = superclass.getDeclaredField("mLastVersion")
            mLastVersion.isAccessible = true

            //2.获取LiveData的mVersion
            val mVersion = liveDataClass.getDeclaredField("mVersion")
            mVersion.isAccessible = true

            //3.将mLastVersion赋值成mVersion
            val mVersionValue = mVersion[this]
            mLastVersion[observerWraper] = mVersionValue
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

七、LiveDataBus

由于LiveData的特性,我们很容易想到让其充当数据总线的角色。相比EventBus,LiveData更容易控制,操作简单,且不用手动去反注册,不会出现内存泄露等问题。我们实现一个简单的LiveDataBus:

object LiveDataBus {
    private var bus: MutableMap<String, MutableLiveData<Any>> = HashMap()
    @Synchronized
    fun <T> with(key: String, type: Class<T>?): MutableLiveData<T> {
        if (!bus.containsKey(key)) {
            bus[key] = MutableLiveData()
        }
        return bus[key] as MutableLiveData<T>
    }
}

bus中我们可以根据不同的组件去保存不同的LiveData对象,使用对应的LiveData进行数据分发。

总结

LiveData需要依赖lifecycle的生命周期管理。LiveData会发送粘性数据,如果不需要,还要手动取消。

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值