Jetpack系列 -- LiveData源码原理解析(解决黏性问题)

一、LiveData是什么?

注意:一般情况下,LiveData要配合ViewModel一起使用的,但是今天是单独使用LiveData,作为学习的话,我们可以只关注LiveData了。

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

二、各种LiveData各种系列使用

1.使用方式一:

MyLiveData.kt 

object MyLiveData {
    // 这里为info1的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
    val info1 : MutableLiveData<String> by lazy { MutableLiveData() }
    init {
        info1.value = "default"
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView: TextView = findViewById(R.id.tv_textview)
        activity_main.xml
        // 1.观察者 眼睛 环节
        MyLiveData.info1.observe(this, {
            textView.text = it
        })
        // 2.触发数据 环节
        MyLiveData.info1.value = "default"
        thread {
            Thread.sleep(3000)
            MyLiveData.info1.postValue("三秒钟后,修改了哦")
        }
        thread {
            Thread.sleep(6000)
            MyLiveData.info1.postValue("六秒钟后,修改了哦")
        }
        // -------------- 下面是 触发修改数据 的写法
        // lambda 写法如下 observe:
        MyLiveData.info1.observe(this, {
        })
        // lambda 写法如下 observeForever:
        MyLiveData.info1.observeForever({
        })
        // 详细写法如下 observe:
        MyLiveData.info1.observe(this, object : Observer<String> {
            override fun onChanged(t: String?) {
            }
        })
        // 详细写法如下 observeForever:
        MyLiveData.info1.observeForever(object : Observer<String> {
            override fun onChanged(t: String?) {
            }
        })
    }
}

2.使用方式二:

MainActivity2.kt

class MainActivity2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        val button = findViewById<Button>(R.id.button)
        button.setOnClickListener {
            startService(Intent(this, MyService::class.java))
            Toast.makeText(MainActivity2@this, "推送服务器启动成功",
                Toast.LENGTH_SHORT).show()
        }
        MyLiveData.data1.observe(this, {
            Log.d("server", "界面可见,说明用户在查看微信列表界面啦,更新消息列表UI界
                    面:${it}")
            Toast.makeText(this, "更新消息列表UI界面成功:${it}",
                Toast.LENGTH_SHORT).show()
        })
    }
}

MyLiveData.kt

object MyLiveData {
    // 这里为info1的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
    val data1: MutableLiveData<String> by lazy { MutableLiveData() }
    // 注意:这里会奔溃 因为是在 thread { 首次实例化MyLiveData对象的,而下面确实setValue就会奔溃
    /*init {
        data1.value = "default"
    }*/
}

MyService.kt

class MyService : Service() {
    override fun onBind(intent: Intent): IBinder? = null
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int
    {
        thread {
            for (x in 1..100000) {
                Log.d("server", "服务器给推你推送消息啦(叮咚声响),消息内容是:${x}")
                MyLiveData.data1.postValue("服务器给推你推送消息啦,消息内容是:${x}")
                Thread.sleep(5000) // 2秒钟推一次
            }
        }
        return super.onStartCommand(intent, flags, startId)
    }
}

3.使用方式三(黏性):

MainActivity3.kt

class MainActivity3 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main3)
        val button = findViewById<Button>(R.id.button)
        button.setOnClickListener {
            MyLiveData.value1.value = "我就是我,不一样的烟火"
            startActivity(Intent(this, MainActivity4::class.java))
        }
    }
}

MainActivity4.kt

class MainActivity4 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main4)
        MyLiveData.value1.observe(this, {
            Toast.makeText(this, "观察者数据变化:$it", Toast.LENGTH_SHORT).show()
        })
    }
}

MyLiveData.kt

object MyLiveData {
    // 这里为info1的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
    val value1 : MutableLiveData<String> by lazy { MutableLiveData() }
}

三、LiveData的源码原理解析

1. MutableLiveData 

继承了LiveData是一个可变的LiveData
是一个被观察者,是一个数据持有者
提供了 setValue 和 postValue方法,其中postValue可以在子线程调用
postValue方法,我们下面会具体分析 

public class MutableLiveData<T> extends LiveData<T> {

    /**
     * Creates a MutableLiveData initialized with the given {@code value}.
     *
     * @param value initial value
     */
    public MutableLiveData(T value) {
        super(value);
    }

    /**
     * Creates a MutableLiveData with no value assigned to it.
     */
    public MutableLiveData() {
        super();
    }

    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

2.MutableLiveData的observe方法参数的this

此接口是宿主生命周期的代表

public interface LifecycleOwner{
	@NonNull Lifecycle getLifecycle();
}

3.MutableLiveData的observe方法参数的Observer

Observer是一个观察者
Observer中有一个回调方法,在 LiveData 数据改变时会回调此方法

public interface Observer<T> {
    /**
     * 当数据改变时调用。
     * @param t 新数据
     */
    void onChanged(T t);
}

4.源码分析

首先我们上面示例中的 LiveData.observe()方法开始。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView: TextView = findViewById(R.id.tv_textview)
        MyLiveData.info1.observe(this, {
            textView.text = it
        })
        thread {
            Thread.sleep(3000)
            MyLiveData.info1.postValue("三秒钟后,修改了哦")
        }
        thread {
            Thread.sleep(6000)
            MyLiveData.info1.postValue("六秒钟后,修改了哦")
        }
    }
}

我们点进observe方法中去它的源码

5.LiveData源码

1)在LiveData的observe方法中
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T>
observer) {
    assertMainThread("observe");
// 一:首先会通过LifecycleOwner获取Lifecycle对象然后获取Lifecycle 的State,如果是DESTROYED直接 return 了。忽略这次订阅
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
        return;
    }
// 二:把LifecycleOwner和Observer包装成LifecycleBoundObserver对象,至于为什么包装成这个对象,我们下面具体讲,而且这个是重点。
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner,
        observer);
// 三:把观察者存到 Map 中
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
// 四:之前添加过LifecycleBoundObserver,并且LifecycleOwner不是同一个,就抛异常
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
// 五:通过Lifecycle和添加 LifecycleBoundObserver观察者,形成订阅关系
    owner.getLifecycle().addObserver(wrapper);
}

到现在,我们知道了LiveData的observe方法中会判断 Lifecycle 的生命周期,
会把LifecycleOwner和Observer包装成LifecycleBoundObserver对象,
然后 Lifecycle().addObserver(wrapper) 
Lifecycle 这个被观察者会在合适的时机 通知 观察者的回调方法。

2)什么时候通知,怎么通知的呢?这个具体流程是什么,继续看下面代码
thread {
    Thread.sleep(3000)
    MyLiveData.info1.postValue("三秒钟后,修改了哦")
}
thread {
    Thread.sleep(6000)
    MyLiveData.info1.postValue("六秒钟后,修改了哦")
}

在点击按钮的时候 LiveData会调用postValue ----> setValue方法,来更新最新的值,这时候我们
的观察者Observer就会收到回调,来更新 TextView。
所以接下来我们先看下 LiveData的setValue方法做了什么,LiveData还有一个postValue方法,我
们也一并分析一下。

6.LiveData的setValue与postValue

1)setValue
// LiveData.java
@MainThread
protected void setValue(T value){
    assertMainThread("setValue");
    mVersion++;
    mData=value;
    dispatchingValue(null); // 注意:这里的分发value值
}

调用了dispatchingValue方法,继续跟代码

void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) { // 如果传递进来的 非null,就进此if
                considerNotify(initiator);
                不管如何判断,都是调用了considerNotify() 方法
                        initiator = null;
            } else { // 如果传递进来的 null,就进此if
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>>
                     iterator =
                     mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    不管如何判断,都是调用了
                    considerNotify() 方法
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

不管如何判断,都是调用了considerNotify()方法

private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }

        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        // 最终调用了observer.mObserver.onChanged((T) mData)方法,
        // 这个observer.mObserver就是我们的 Observer接口,然后调用它的onChanged方法。
        observer.mObserver.onChanged((T) mData);
        // 恭喜恭喜 :到现在整个被观察者数据更新通知观察者这个流程就通了。
    }
2)postValue

子线程发送消息通知更新 UI,嗯?Handler 的味道

// LiveData.java
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        // 利用Handler切换到主线程去执行
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

可以看到一行关键代码
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
点 postToMainThread 方法进去看下

// ArchTaskExecutor.java
    privateTaskExecutor mDelegate;

    @Override
    public void postToMainThread(Runnable runnable) {
        mDelegate.postToMainThread(runnable);
    }

看到 mDelegate 是 TaskExecutor对象,现在目标是看下 mDelegate 的具体实例对象是谁

// ArchTaskExecutor.java
private ArchTaskExecutor(){
    mDefaultTaskExecutor=new DefaultTaskExecutor();
    mDelegate=mDefaultTaskExecutor; // 目前的重点是看下DefaultTaskExecutor是个啥
}

然后看它的postToMainThread方法

// DefaultTaskExecutor.java
    privatevolatileHandler mMainHandler;

    @Override
    public void postToMainThread(Runnable runnable) {
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    // 实例了一个 Handler 对象,注意构造参数 Looper.getMainLooper() 是主线的 Looper。
                    // 那么就可做到线程切换了。
                    mMainHandler = new Handler(Looper.getMainLooper()); // 注意:这里主
                    线程已经切换过来了
                }
            }
        }
        //noinspection ConstantConditions
        // 调用post 方法 注意:重点看runnable,这里面就是真正主线程的执行功能了
        mMainHandler.post(runnable); 
    }

下面看下这个 Runnable
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
这里面的方法参数是mPostValueRunnable是个 Runnable,我们看下代码

// LiveData.java
    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            // 注意:postValue方法其实最终调用也是setValue方法,然后和setValue方法走的流程就是一样的了,
            // 这个上面已经分析过了
            setValue((T) newValue);
        }
    };

7.LifecycleBoundObserver

我们要详细看一下LifecycleBoundObserver类了,它包装了LifecycleOwner和Observer,这就是
接下来的重点内容了。

1)observe
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T>
            observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        // 用LifecycleBoundObserver对LifecycleOwner 和 Observer进行了包装
        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
        GenericLifecycleObserver {
    @NonNull
    final LifecycleOwner mOwner;
    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T>
            observer) {
        super(observer);
        mOwner = owner;
    }
}

两个参数,一个 owner被成员变量mOwner存储,observer参数被ObserverWrapper的 mObserver存储。
LifecycleEventObserver是LifecycleObserver的子接口里面有一个onStateChanged方法,这个方法会在 Activity、Fragment 生命周期回调时调用(这个和Lifecycle有关)
ObserverWrapper 是Observer包装类

2)ObserverWrapper

活跃状态指的是 Activity、Fragment 等生命周期处于活跃状态

private abstract class ObserverWrapper {
    final Observer<? super T> mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

    // 获取了我们的 Observer 对象,存储在 成员变量mObserver身上
    ObserverWrapper(Observer<? super T> observer) {
        mObserver = observer;
    }

    // 抽象方法,当前是否是活跃的状态
    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        mActive = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += mActive ? 1 : -1;
        if (wasInactive && mActive) {
            // 可以继承 LiveData 来达到扩展 LiveData 的目标,并且是在活跃的状态调用
            onActive();
        }
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            // 可以继承 LiveData 来达到扩展 LiveData 的目标,并且是在非活跃的状态调用
            onInactive();
        }
        if (mActive) {
            // 活跃状态,发送最新的值,来达到通知的作用,dispatchingValue(this) 方法咋这么眼熟,
            // 对之前在 LiveData 调用 setValue 方法时,最终也会调用到此方法。
            // 那ObserverWrapper类中的dispatchingValue这个方法是在activeStateChanged方法中调用,
            // 那activeStateChanged啥时候调用呢?
            // 我来看下ObserverWrapper的子类也就是最重要的那个类LifecycleBoundObserver,
            // 现在看它的完整代码(看下面代码 LifecycleBoundObserver完整代码)
            dispatchingValue(this);
        }
    }
}

LifecycleBoundObserver完整代码

class LifecycleBoundObserver extends ObserverWrapper implements
        GenericLifecycleObserver {
    @NonNull
    final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T>
            observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        // 判断当前的 Lifecycle 的生命周期是否是活跃状态,会在回调观察则 Observer 的时候进行判断,
        // 只有在活跃状态,才会回调观察者Observer的onChanged方法。
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        // onStateChanged每次 Activity、Fragment的生命周期回调的时候,都会走这个方法。
        // 获取Lifecycle对象然后获取Lifecycle 的State如果为DESTROYED则移除观察者,
        // 在 Activity、Fragment的生命周期走到 onDestroy 的时候,就会取消订阅,避免内存泄漏。
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        // 调用父类ObserverWrapper 的activeStateChanged方法,
        // 层层调用到观察者Observer的onChanged方法。(自己看下源码一目了然)
        activeStateChanged(shouldBeActive());
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        // 移除观察者Observer,解除订阅关系。
        mOwner.getLifecycle().removeObserver(this);
    }
}

四、自定义JLiveDataBus解决黏性问题

JLiveDataBus.kt

object JLiveDataBus {

    private const val TAG = "JLiveDataBus"

    private val busMap: MutableMap<String, BusMutableLiveData<Any>> by lazy { HashMap<String, BusMutableLiveData<Any>>() }

    @Synchronized
    fun <T> with(key: String, type: Class<T>, isStick: Boolean = true): BusMutableLiveData<T> {
        Log.d(TAG, "with isStick $isStick")
        if (!busMap.containsKey(key)) {
            busMap[key] = BusMutableLiveData(isStick)
        } else {
            (busMap[key] as BusMutableLiveData<T>).isStick = isStick
        }
        return busMap[key] as BusMutableLiveData<T>
    }


    class BusMutableLiveData<T> private constructor() : MutableLiveData<T>() {

        // 启用粘性事件
        var isStick: Boolean = false

        // 次构造函数,必须调用主构造函数
        constructor(isStick: Boolean) : this() {
            Log.d(TAG, "constructor isStick $isStick")
            this.isStick = isStick
        }

        // 重写 增加hook
        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)
            if (!isStick) {
                // 不启用粘性事件
                hook(observer = observer)
                Log.d(TAG, "不启动粘性事件")
            } else {
                Log.d(TAG, "启动粘性事件")
            }
        }

        private fun hook(observer: Observer<in T>) {
            // TODO 1.利用反射得到mLastVersion
            // 获取到LiveData类中的mObservers对象
            val liveDataClass = LiveData::class.java
            val mObserversField: Field = liveDataClass.getDeclaredField("mObservers")
            // 设置权限,私有修饰也可以访问
            mObserversField.isAccessible = true
            // 获取到mObservers这个成员变量的对象
            val mObservers: Any = mObserversField.get(this)
            // 获取到mObservers的class对象
            val mObserversClass: Class<*> = mObservers.javaClass
            // 获取到mObservers对象的get方法
            val get: Method = mObserversClass.getDeclaredMethod("get", Any::class.java)
            get.isAccessible = true
            // 执行get方法
            val invokeEntry: Any = get.invoke(mObservers, observer)
            // 获取到entry中的value
            var observerWraper: Any? = null
            if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
                observerWraper = invokeEntry.value
            }
            if (observerWraper == null) {
                throw NullPointerException("observerWraper is null.")
            }
            // 获取到observerWraper的类对象
            val supperClass: Class<*> = observerWraper.javaClass.superclass!!
            val mLastVersion: Field = supperClass.getDeclaredField("mLastVersion")
            mLastVersion.isAccessible = true

            // TODO 2.得到mVersion
            val mVersion: Field = liveDataClass.getDeclaredField("mVersion")
            mVersion.isAccessible = true

            // TODO 3.mLastVersion = mVersion
            val mVersionValue: Any = mVersion.get(this)
            mLastVersion.set(observerWraper, mVersionValue)
        }
    }

}

BusActivity.kt

class BusActivity : AppCompatActivity() {

    private lateinit var binding: ActivityBusBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityBusBinding.inflate(layoutInflater)
        setContentView(binding.root)

        JLiveDataBus.with("test1", String::class.java, false).observe(this) {
            binding.busTv.text = it
        }

        thread {
            Thread.sleep(2000)
            JLiveDataBus.with("test1", String::class.java).postValue("新数据")
        }

    }
}

startActivity

JLiveDataBus.with("test1", String::class.java).value = "老数据"
        textView.setOnClickListener {
            startActivity(Intent(activity, BusActivity::class.java))
        }

由于我们在BusActivity使用的是不启用粘性,JLiveDataBus.with("test1", String::class.java, false).observe(this),所以当BusActivity启动时不会调用binding.busTv.text = "老数据",延迟2S后,正常接收到启动后的 新数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sziitjin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值