LiveData学习

几个不错的网址:
App开发架构指南(谷歌官方文档译文)
google源码 mvvm
感知生命周期的数据 – LiveData
App体系结构指南
https://github.com/BodhiSun/JetpackTestDemo
https://github.com/vi8er/MVVMFrame
MediatorLiveData#addSource之Android Architecture Components踩坑记录
Android LiveData 使用详解
Android之MVVM架构指南(四):LiveData
Android LiveData Transformations
安卓架构组件(4)-LiveData
Android Jetpack 架构组件最佳实践
LiveData使用解析并记录坑
LiveData 更新流程分析,小编在学习LiveData的时候有个疑问

@Override
    protected void onResume() {
    
    
        super.onResume();
        MutableLiveData<String> mutableLiveData = new MutableLiveData<>();
        Log.i("test", "onActivityCreated: xxxxxxxxxxx");
        mutableLiveData.observe(this, new Observer<String>() {
    
    
            @Override
            public void onChanged(String s) {
    
    
                Log.e("test", "onChanged:"+s);
            }
        });
        mutableLiveData.setValue("新值");
        //
    }

看如上代码,setValue在observe之后,onChanged方法可以触发,但是setValue写在observe之前的时候,仍然可以触发onChanged方法,如下

@Override
    protected void onResume() {
    
    
        super.onResume();
        MutableLiveData<String> mutableLiveData = new MutableLiveData<>();
        Log.i("test", "onActivityCreated: xxxxxxxxxxx");
        mutableLiveData.setValue("新值");
        mutableLiveData.observe(this, new Observer<String>() {
    
    
            @Override
            public void onChanged(String s) {
    
    
                Log.e("test", "onChanged:"+s);
            }
        });
        //
    }

这就有点疑问了,先添加观察者,后setValue更新值可以触发onChanged方法这个没有疑问,但是先setValue,后添加观察者,还能触发onChanged 这个就很是不解,如果这样的话,onChanged方法的触发会不会和setValue没有关系呢(结果是如果setValue注释掉的话,只有添加观察者,onChanged方法是不会触发的),下面开始跟源码回答这3个问题:
1、先添加观察者 observe,后setValue,onChanged方法触发的流程
2、先setValue,后添加观察者observe,onChanged方法触发的流程
3、只添加观察者observe,没有触发onChanged方法的流程
说之前交给大家一个查看方法调用栈的方法,输出日志信息

Log.e("test", "onChanged:"+Log.getStackTraceString(new Throwable()));

注意:这里小编把这个观察和setValue放到了onResume方法中,因为此时Activity的状态是Resume状态,执行观察的流程不是太多,如果你放到onCreate中去看(界面显示是onResume),在流程相关的方法其他方法中打断点时会发现执行很多次(比如lifcycle相关的生命周期执行了create start resume 影响分析onChanged方法的调用流程)

先添加观察者 observe,后setValue,onChanged方法触发的流程

mutableLiveData.observe(this, new Observer<String>() {
    
    
            @Override
            public void onChanged(String s) {
    
    
                Log.e("test", "onChanged:"+s);
                //Log.e("test", "onChanged:"+Log.getStackTraceString(new Throwable()));
            }
        });
        mutableLiveData.setValue("新值");

mObservers.putIfAbsent 方法会将观察者加入mObservers集合

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

看下liveData中setValue调用时

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    
    
        if (mDispatchingValue) {
    
    
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
    
    
            mDispatchInvalidated = false;
            if (initiator != null) {
    
    
                considerNotify(initiator);//先setValue后观察,会执行这个方法
                initiator = null;
            } else {
    
    
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
    
    
                    considerNotify(iterator.next().getValue());//先观察后setValue会执行这个方法
                    if (mDispatchInvalidated) {
    
    
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

只观察不调用setValue的时候为何没有触发onChanged方法,看下
首先跟setValue方法做了什么事情,首先是mVersion自加,dispatchingValue中的一些变量的设置,以及根据观察者做的处理
,这里没有调用setValue方法,所以onChanged方法没有触发,会不是因为mVersion的没有改变,或者dispatchingValue中的一些变量没有改变导致的onChanged方法没有触发呢?思考一下

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

livedata中的considerNotify

@SuppressWarnings("unchecked")
    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;
        }//不调用setValue方法时,这个地放直接执行了return方法,所以下面的onChanged方法的回调不会执行了
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

看下onChanged方法的调用栈,流程就很清楚了(先setValue,后观察的调用栈信息)

2020-09-22 22:40:46.343 32726-32726/com.tt.test E/test: onChanged:java.lang.Throwable
        at com.tt.test.aac.AACActivity$1.onChanged(AACActivity.java:36)
        at com.tt.test.aac.AACActivity$1.onChanged(AACActivity.java:32)
        at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
        at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:146)
        at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:468)
        at androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged(LiveData.java:425)
        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:354)
        at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:196)
        at androidx.lifecycle.LiveData.observe(LiveData.java:205)
        at com.tt.test.aac.AACActivity.onResume(AACActivity.java:32)

有不清楚的可以留言
如何想看只写观察者的流程,可以在observe上加断点,查看。之所以Activity或者Fragment生命周期改变时,会执行observe方法相关的方法,是因为Activity或Fragment生命周期改变时会调用

handleLifecycleEvent

方法,以Activity onDestroy方法为例
最终在FragmentActivity方法中会有如下调用

/**
     * Destroy all fragments.
     */
    @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        mFragments.dispatchDestroy();
        mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
    }
AACActivity extends AppCompatActivity
AppCompatActivity extends FragmentActivity

判断应用是否在前台

之前的写法:

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
    
    
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    
    
              
            }
 
            @Override
            public void onActivityStarted(Activity activity) {
    
    
            }
 
            @Override
            public void onActivityResumed(Activity activity) {
    
    
         
            }
 
            @Override
            public void onActivityPaused(Activity activity) {
    
    
              
            }
 
            @Override
            public void onActivityStopped(Activity activity) {
    
    
            }
 
            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
    
 
            }
 
            @Override
            public void onActivityDestroyed(Activity activity) {
    
    
         
            }
        });

现在的写法:
使用google Lifecycle判断应用在前台还是后台的方法(小编把lifecycle相关的依赖都写上了,如下)

def lifecycle_version = "2.3.0-alpha07"
    def arch_version = "2.1.0"
    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    // Lifecycles only (without ViewModel or LiveData)
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
    // Saved state module for ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
    // Annotation processor
    kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
    // alternately - if using Java8, use the following instead of lifecycle-compiler
    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
    // optional - helpers for implementing LifecycleOwner in a Service
    implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
    // optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
    implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
    // optional - ReactiveStreams support for LiveData
    implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version"
    // optional - Test helpers for LiveData
    testImplementation "androidx.arch.core:core-testing:$arch_version"

首先定义一个实现了LifecyclerObserver接口的类:

public class LifecyclerChecker implements LifecycleObserver

然后在这个类中加入如下代码:

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onAppBackground() {
    
    
        // 应用进入后台
        Log.e("test","LifecycleChecker onAppBackground ON_STOP");
    }
 
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onAppForeground() {
    
    
        // 应用进入前台
        Log.e("test","LifecycleChecker onAppForeground ON_START");
    }

上面的方法名是随便起的,重要的是注解

@OnLifecycleEvent(Lifecycle.Event.ON_STOP) 表示应用进入后台
@OnLifecycleEvent(Lifecycle.Event.ON_START)表示应用进入前台

最后,在合适的地方调用下面的方法:

ProcessLifecycleOwner.get().getLifecycle().addObserver(new LifecycleChecker()); //可以选择在自定义的Application的onCreate中调用

下面这个方法无论是在Application的onCreate中调用,还是在Activity的onCreate或者其他的生命周期函数中调用都可以,你可以在自己喜欢的地方调用。
ProcessLifecycleOwner判断Android应用程序前后台切换
android livedata组件学习
视频录制
日历收集项目
如何配置Tigase的SSL/TLS证书?
nio和netty
2020年9月17 23:30 ylxy3

猜你喜欢

转载自blog.csdn.net/w690333243/article/details/108655078