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

贪多嚼不烂,欲速则不达

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

目 录CONTENT

文章目录

Jetpack组件-二-Livedata

慢行的骑兵
2021-09-11 / 0 评论 / 0 点赞 / 226 阅读 / 2,234 字
  • 本篇笔记主要是记录Livedata的原理和源码分析。

一.简介

  • Livedata是一个可观察的数据持有者,与常规observable不同,LiveData是生命周期感知的。

  • 补充一下接口和观察者的区别:本质上没什么区别,只不过接口是1对1,观察者是不单单只是1对1;

  • Livedata优势

二.基本使用

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 s) {
                Log.d(TAG, "触发onChanged:" + s);
            }
        });
        
        //发生数据
        mutableLiveData.postValue("发送数据");
    }
}
  • 注意:设置监听和发送数据的步骤是不分先后顺序的,至于原因,了解源码后就会明白。
  • 本篇笔记的重点是源码分析和实现原理,基本用法就略写了。

三.源码分析

  • 源码从监听方法开始或者从发送数据方法开始都可以,只不过内部代码的执行流程会有点不同,我们选取一个方向即可。先从设置监听方法开始。
  • 提示:在分析Livedata源码之前,请先去分析一下Lifecycle的源码。因为涉及到的Lifecyle源码相关已经写过一篇笔记,这里涉及到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)可以知道,最终会执行ObserverWrapper的onStateChanged方法,而ObserverWrapper是抽象类,故执行其子类的onStateChanged方法。那onStateChanged被调用的时机是什么时候呢?同样的跟Lifecyle一样,被观察者的生命周期方法调用后就会触发onStateChanged方法。

  • 当postvalue的时候做的事情实际上就是一件,将value存储到mdata中并mVersion++。然后目标的activity的生命周期方法被触发的时候就会调用 ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event)方法,最终是调用mLifecycleObserver.onStateChanged(owner, event)的方法,最终是调用Livedata中的LifecycleBoundObserver类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;
        }
        //6.调用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() {
    }

    //6.1.当activity生命周期改变的时候,就会回调该方法(需要先了解Lifecyle的原理)
    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner 
        //onCreate执行的时候mActive = false 
        //执行了onStart或者onResume方法时候mActive = true 
        mActive = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += mActive ? 1 : -1; 
        if (wasInactive && mActive) {
            onActive();	  //空实现
        }
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            onInactive(); //空实现
        }
        
        //12.activity的onStart方法调用了,进入if语句
        
        //6.2.如果被观察者是处于活动状态(activity执行了onStart或者onResume方法),才进入if语句
        if (mActive) {
            //7.调用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
        if (initiator != null) {
            //8.在3.5中分析considerNotify
            considerNotify(initiator);		//12.1继续执行
            initiator = null;
        } else {
            //11.1.集合中有数据,故会执行for循环,这里会执行一次considerNotify(执行次数由集合的长度决定)
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                //11.2.发送数据是activity的onCreate方法中调用的,故执行的结果跟3.5一样。
                //此时,就有问题了,监听设置了,数据也发送了,回调方法没执行,不着急。我们在3.5中分析
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

3.5分析considerNotify

private void considerNotify(ObserverWrapper observer) {
    
    //11.3.再次回到该方法
    
    //9.验证UI是否显示
    //根据6.2可以知道,activity只调用onCreate方法,但是还未调用onStart或者onResume方法,是不会执行到这里来的
    //而当调用onStart或者onResume方法!observer.mActive = false
    //问题:如果我们在activity的其它生命周期方法中设置监听,而且还设置多次,那么源码的执行逻辑是如何的?当我们按照笔记的思路去把源码分析一边,再来思考这个问题,应该也不难的。先有印象,我们现在该去分析发送数据的方法的源码了
    
    //11.4.若setValue是在onCreate方法设置,则进入,若在onStart或者onResume方法执行则相反
    //我们这里就按照二中的写法来分析,那么当activity的onCreate方法执行完后到此就结束了。
    //那么回调没有得到onChanged触发,下面该如何分析?
	//当onCreate方法执行完,activity在执行onStart方法时,又会触发步骤6中的方法,回到步骤6继续分析
    
    //12.2.不进入
    if (!observer.mActive) {	      
        return;
    }

    //被观察者是否处于非活动状态
    
    //12.3.不进入
    if (!observer.shouldBeActive()) {		//11.5.同11.4	
        observer.activeStateChanged(false);
        return;
    }
    
    //在还未调用postValue方法之前,mLastVersion的值为-1,mVersion的值也为-1
    //mLastVersion的赋值时机是LifecycleBoundObserver被创建的时候
    //mVersion的赋值时机是在activeStateChanged方法被调用的时候
    //也就是说,只设置监听,不管实在activity的onCreate还是onStart或onResume中设置,都会进入if语句
    //即不触发onChanged回调
    
    //12.4.此时不进入(mLastVersion = -1,mVersion = 0)
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    
    //12.5.mLastVersion = mVersion = 0
    observer.mLastVersion = mVersion; 
    
    //12.6.触发回调				回到3.7中
    observer.mObserver.onChanged((T) mData);	
}

3.6.分析setValue

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

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    //10.mVersion + 1		设置一次的情况mVersion = 0
    mVersion++;			
    //10.1.存储到成员变量中
    mData = value;		
    //11.分析dispatchingValue,回到3.4中看对应步骤的注释
    dispatchingValue(null);
}

3.7.总结

  • 源码分析的流程跟被观察者的生命周期方法执行关联性很强,关于activity的onResume的方法被调用后,代码的执行流程,可以按照上面的同样的方式进行分析。

  • 另外,监听设置多次,已经在不同被观察者不同的生命周期方法中设置,如果把Lifecycle的笔记和上面的笔记梳理清楚了,其源码的执行流程的分析我觉得也不难了。有兴趣大家可以自行研究。

0

评论区