侧边栏壁纸
博主头像
慢行的骑兵博主等级

贪多嚼不烂,欲速则不达

  • 累计撰写 41 篇文章
  • 累计创建 27 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Android Jetpack | Livedata

慢行的骑兵
2021-09-11 / 0 评论 / 0 点赞 / 1,105 阅读 / 2,450 字

一.前言

  • 本篇主线包含三个方面,Livedata的作用和简单使用、实现原理(源码主线分析)、粘性事件的产生及处理方式和递归调用容错处理机制;
  • 在学习Livedata之前,需要先有Lifecycle的基础才行;

二.Livedata的作用和简单使用

2.1.作用

  • Livedata是一个可观察的数据持有者,与常规observable不同,LiveData是生命周期感知的。
  • 补充一下接口和观察者的区别:本质上没什么区别,只不过接口是1对1,观察者是不单单只是1对1;
  • Livedata官方文档
  • 作用:在Android 开发中实现 响应式、解耦、安全 架构的关键工具;
    • 在MVVM架构中,通过数据驱动UI;
      • ViewModel 通过 LiveData 持有数据,View 层观察数据变化,数据变更时 UI 自动刷新。在View层和ViewModel层通信起个桥梁作用;
    • 自动处理生命周期,避免内存泄漏;

2.2.简单使用

  • 依赖
implementation("androidx.lifecycle:lifecycle-livedata:2.9.2")
  • 使用
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //创建对象
        MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();

        //设置监听
        mutableLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String str) {
                Log.d(TAG, "onChanged:" + str);
            }
        });

        //发生数据
        mutableLiveData.postValue("post数据");
    }
}
  • 注意:设置监听和发送数据的步骤是不分先后顺序的,至于原因,了解源码后就会明白。

三.实现原理

  • 在分析Livedata源码之前,默认已经熟悉了Lifecycle的核心原理;

3.1.分析设置监听的方法

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    //1.判断组件的生命周期是否结束了	
    //这里我们看到了Lifecycle的影子,下方也有
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    
    //2.把组件和观察者都封装到了LifecycleBoundObserver
    //参数1:组件
    //参数2:观察者
    //在3.2中分析LifecycleBoundObserver
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    
    //3.每当添加一个观察者,会把观察者添加到map集合中(此时,mObservers就有值了)
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    
    //...
    
    //决定生命周期的感知
    //4.给组件的生命周期添加了一个观察者(即Livedata内部使用了Lifecycle)
    owner.getLifecycle().addObserver(wrapper);	
}

3.2.LifecycleBoundObserver

  • 在分析该类之前,我们先回顾一个Lifecycle的原理,根据owner.getLifecycle().addObserver(wrapper)可以知道,最终会执行wrapper(LifecycleBoundObserver类)的onStateChanged方法。onStateChanged被调用的时机跟Lifecyle一样,被观察者的生命周期方法调用后就会触发onStateChanged方法。
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) {
     	//DESTROYED状态,回收观察者
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        //5.调用activeStateChanged方法(被观察者生命周期方法调用时,触发该方法)
        //在3.3中分析activeStateChanged
        //shouldBeActive:被观察者的是否处于可见状态
        activeStateChanged(shouldBeActive());
    }

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

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

3.3.分析activeStateChanged

private abstract class ObserverWrapper {
    final Observer<? super T> mObserver;	//观察者(在3.2中已经被赋值)
    boolean mActive;
    int mLastVersion = START_VERSION;

    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;
        }

        //onCreate执行的时候mActive = false 
        //执行了onStart或者onResume方法时候mActive = true 
        mActive = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += mActive ? 1 : -1; 
        //UI从不显示到显示
        if (wasInactive && mActive) {
            onActive();	  //空实现
        }
        //UI从显示到不显示
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            onInactive(); //空实现
        }

        //5.2.如果被观察者是处于活动状态(activity执行了onStart或者onResume方法),才进入if语句
        if (mActive) {
            //6.调用dispatchingValue,在3.4中分析
            dispatchingValue(this);
        }
    }
}

3.4分析dispatchingValue

  • dispatchingValue内部的一些boolean变量是防止Livedata递归调用时做的容错处理
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        //根据initiator是否为null来决定 是直接调用considerNotify函数还是 循环mObservers之后再调用considerNotify函数
        //6.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;
}

3.5分析considerNotify

private void considerNotify(ObserverWrapper observer) {
	//如果观察者所在的宿主不活跃了,不分发
    if (!observer.mActive) {	      
        return;
    }
	
    //动态判断当前观察者(Observer)是否处于“活跃状态”,非活跃状态,则不分发
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    
    //observer.mLastVersion >= mVersion,不分发
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    
    observer.mLastVersion = mVersion; 
    //调用ObserverWrapper中mObserver(该成员对应为观察者,赋值时机为LifecycleBoundObserver构造函数被调用时主动调用了ObserverWrapper的构造函数,对mObserver进行赋值)
    //即:7.调用观察者的onChanged函数
    observer.mObserver.onChanged((T) mData);	
}
  • 如果considerNotify内部满足分发的条件,则会回调onChanged函数。到此,LiveData设置监听(observe)& 触发回调(onChanged)的逻辑我们就走通了。

3.6.分析setValue

  • 先补充一点,setValue和postValue区别:
  • setValue 只能在子线程上运行,postValue 可以在任意线程上运行(底层使用到了handler,postValue 最终还是调用的是setValue );
//该成员变量是正在的数据持有者
private volatile Object mData;

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;	//对3.5的影响		
    mData = value;
    //参数传null和不传null的区别就是如果传null将会通知所有的观察者,反之仅仅通知传入的观察者
    dispatchingValue(null);
}

3.7.执行流程

Livedata代码执行流程

四.粘性事件和递归调用的容错处理

4.1.粘性事件产生的原因

  • 当监听设置在发送数据之后,监听位置对应的回调依旧可以触发,会收到最后一次发送的数据,该情况称为粘性事件;
  • 原因:LiveData 内部维护一个 mVersion 计数器,每次数据更新时递增,观察者内部保存一个 mLastVersion 记录最后一次接收的版本,当观察者订阅时,在considerNotify函数中,如果 mVersion > mLastVersion,则立即分发最新数据(即触发观察者的onChanged回调);

4.2.粘性事件的处理

  • 要实现非粘性或可控的粘性事件,可以通过 Hook 方式修改 LiveData 的行为:通过反射得到 LiveData 的内部版本号,使得新观察者的 mLastVersion 与当前 mVersion 相等,避免立即触发通知。
package com.jack.livedata_simple;

import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

public class NonStickyMutableLiveData<T> extends MutableLiveData {
    private boolean stickFlag=false;

    @Override
    public void observe( LifecycleOwner owner,  Observer observer) {
        super.observe(owner, observer);
        if(!stickFlag) {
            hook(observer);
            stickFlag=true;
        }
    }

    //在这里去改变onChange的流程
    private void hook(Observer<? super T> observer) {
        try {
            //1.得到mLastVersion
            //获取到LiveData的类中的mObservers对象
            //SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers
            Class<LiveData> liveDataClass = LiveData.class;
            Field mObserversField = liveDataClass.getDeclaredField("mObservers");
            mObserversField.setAccessible(true);
            
            //获取到这个成员变量的对象
            Object mObserversObject = mObserversField.get(this);
            //得到map对应的class对象
            Class<?> mObserversClass = mObserversObject.getClass();
            //获取到mObservers对象的get方法   entry
            Method get = mObserversClass.getDeclaredMethod("get", Object.class);
            get.setAccessible(true);
            //执行get方法   mObservers.get(observer)
            Object invokeEntry=get.invoke(mObserversObject,observer);
            //定义一个空的对象
            Object observerWraper=null;
            if(invokeEntry!=null && invokeEntry instanceof Map.Entry){
                observerWraper=((Map.Entry)invokeEntry).getValue();//ObserverWrapper
            }
            if(observerWraper==null){
                throw new NullPointerException("observerWraper is null");
            }
            //得到ObserverWrapper的类对象  编译擦除问题会引起多态冲突所以用getSuperclass
            //getClass()返回对应的当前正在运行时的类所对应的对
            Class<?> superclass = observerWraper.getClass().getSuperclass();//mLastVersion
            Field mLastVersion = superclass.getDeclaredField("mLastVersion");
            mLastVersion.setAccessible(true);
            //2.得到mVersion
            Field mVersion = liveDataClass.getDeclaredField("mVersion");
            mVersion.setAccessible(true);
            //3.把mVersion的数据填入到mLastVersion中
            Object mVersionValue=mVersion.get(this);
            mLastVersion.set(observerWraper,mVersionValue);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

4.3.递归调用的容错处理

  • 递归调用可能发生在以下情况:
    • 在 onChanged() 回调中再次修改 LiveData 的值
    • 多个相互观察的 LiveData 形成循环依赖
  • 容错机制实现-关键保护逻辑
    • 递归检测:
      • 当 dispatchingValue() 被递归调用时,mDispatchingValue 已经为 true
      • 设置 mDispatchInvalidated = true 并立即返回
    • 无效分发处理:
      • 外层分发会检测到 mDispatchInvalidated 被标记
      • 中断当前迭代,重新开始分发流程
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;
}
  • 假设以下递归调用场景:
    • 第一次 setValue() 调用:
      • mDispatchingValue = false → 进入分发流程
      • 开始通知观察者
    • 在某个 onChanged() 回调中再次调用 setValue():
      • 检测到 mDispatchingValue = true
      • 设置 mDispatchInvalidated = true
      • 立即返回
    • 外层分发(for循环)检测到 mDispatchInvalidated:
      • 中断当前观察者列表的遍历
      • 重新开始分发流程(此时包含最新的值)

五.总结

  • 本文通过对Livedata的核心原理以及粘性事件产生跟处理和递归调用的容错处理的逻辑进行讲解。合理使用Livedata在Mvvm架构中有助于写出更易于维护和管理的代码。
0

评论区