LiveData小知识点,何时注册Observer

本文探讨了在Android中使用LiveData时,为何应在Activity的onCreate()方法中注册Observer,而不是onResume()。作者通过实验发现,如果在onResume()中注册Observer,当 LiveData 值已改变并再次返回到Activity时,会导致回调执行两次。分析源码后指出,标准做法是在onCreate()注册Observer,或保持Observer对象为成员变量。同时,作者分享了对Jetpack Room与LiveData结合使用的看法,并反思了自己的学习态度和时间管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LiveData学习使用

记录一个在使用LiveData是遇到的有趣问题。由这个问题我们知道,在Activity中设置LiveData的Observer的时候,需要在onCreate中去设置。

起初些demo。主要是为了验证在SecondActivity,改变LiveData的值的时候,MainActivity的Observer何时被回调。
MainActivity代码
MainActivity的代码
SecondActivity的代码
在这里插入图片描述
功能其实非常简单,定义一个单例的LiveData对象,然后在SecondActivity中改变LiveData的值,看MainActivity中的Observer是否会回调。
结论是再没有回到MainActivity的时候自然不会被回调,这个是符合预期的。
但是有一点我呢提,我发现回到MainActivity之后,居然执行了两次回调。日志如下。在这里插入图片描述
怎么回事呢,看了一下,我设置监听是在onResume中,再次回到Main的时候又会设置一次监听,但是值已经变化了啊,为什么还会被回调呢。那肯定就是在添加observer的时候还有些判断,可以直接触发回调。看下LiveData的observer源码。
在这里插入图片描述
那就应该是标红的这一行中有触发回调的逻辑了。进到方法看一下。实际实现是在LifecycleRegistry.java中,代码如下

public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        // 判断这个observer对象是否已经被添加过了,所以如果不想重复触发可以讲传入的observer设为成员变量,后面讲一下
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        // ** 重点就在于这个state的计算 ,下一段代码就关于state的计算**
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }
private State calculateTargetState(LifecycleObserver observer) {
        Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);

        State siblingState = previous != null ? previous.getValue().mState : null;
        State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
                : null;
        return min(min(mState, siblingState), parentState);
    }

按照现在的这种讲Observer注册写道onResume中,LiveData被改变一次,只要Main没有被Destroy,每次进入Main页面都要走一次回调,这肯定是不行的。

根据源码展示,有两种方法,一种是在onCreate中注册,其实这本就是标准用法。另一种方法是将observer对象设置为成员变量(这一点我们可以从源码中看到)。具体方法可以自己看看。

今天还看了一下Jetpack中的Room,结合LiveData使用,简直是无敌了。过几天也写一下自己的理解。

总结

最近一直在找工作,因为感觉在OPPO继续呆着,做的业务也没啥意思了,很想做新模块的开发,可是连续面了五家,全部倒再一面,我还是两年前第一次找工作那样,什么问题我都能回答一些,但是往深了问就不知道了。两年前凭借面试表现,怎么面试都能拿下offer,因为当时作为一个工作一年的人来说我所掌握的知识的广度和深度,的确是比大部分人优秀的。但是现在我已经是一个工作三年的人了,对于基础知识的深度还是和以前一样,广度甚至变小了。在OPPO一直是埋头干事情,对现有模块添加一点东西,或者解决一些繁琐的业务bug。不涉及架构设计能力的提升,也不用学习任何的新东西,我就完全能够应付现有的工作需要。并且19年一整年,都是十点半以后下班的节奏,整个人都是非常疲惫的,接着就是完全忽略了对新技术的学习。也不再关注行业动态了。起先我一直都在埋怨OPPO这种没有技术氛围的工作环境,但是现在我才逐渐意识到,其实这些环境是一小部分因素,重点还是自己怎么做。我的室友,作为一名产品经理,每天比我回来的还晚,但是19年他看了大概有将近二十本书,并且大多数时候都是七点起床去健身。时间是靠自己争取的,知识也是靠自己汲取的。所以我觉得我需要重新开始好好学习一些非常好的东西。并且好好复习基础知识,即使我还是没办法找到心仪的工作,即使我可能还要继续留在OPPO,但是我一定会成为更优秀的人,我要为自己正名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值