LiveData听完课后的疑问

LiveData听完课后的疑问

疑问一:

老师视频里说到,LiveData 分发消息默认情况下是不能跨页面的,原因是什么?


结合ViewModel拿到LiveData对象吗,不同的页面拿到相同的ViewModel,然后在里面定义共享数据的LiveData,不相当是类似跨页面传递数据了吗?


比方说,我在A页面实现接口回调传递LiveData,B页面去实现拿到LiveData,LiveData源码里面setValue(),会保存一个临时的Data保证数据最新,那么我在A页面怎么setValue,B页面拿到的LiveData里面的Value其实也是A传过来最新的啊


还是说老师课程说的LiveData默认情况只是单纯使用LiveData对象,setValue(),或者是observer()都只能在当前宿主页面的意思,我理解错了,因为我看后面实战,老师也只是将LiveData做成单例就能跨页面了


疑问二:

问答区有个同学提问,没看到老师解答意思


相关代码:

/**
 * 对外暴露的observer() 方法
 */
fun observerSticky(owner: LifecycleOwner, sticky: Boolean, observer: Observer<in T>) {
    //允许指定注册的观察则 是否需要关心黏性事件
    //sticky =true, 如果之前存在已经发送的数据,那么这个observer会受到之前的黏性事件消息
    owner.lifecycle.addObserver(LifecycleEventObserver { source, event ->
        //监听 宿主 发生销毁事件,主动把livedata 移除掉。

        /*
          todo
              这一块有问题,假设Activity A发送了一个事件,Activity B和Activity C都需要处理同一个粘性事件。
              如果A先进入B,B收到粘性事件并处理,最后销毁B,那么此时StickyLiveData也销毁了,
              然后再从A进入C的话,粘性事件就没了;同样的先处理C的话,当C销毁后B里面要处理的粘性事件也没了。
         */

        if (event == Lifecycle.Event.ON_DESTROY) {
            eventMap.remove(eventName)
        }
    })
    super.observe(owner, StickyObserver(this, sticky, observer))
}


这个是不是说 eventMap.remove(eventName)注释掉,不用处理了,让LiveData在DESTROY自动销毁掉


正在回答

登陆购买课程后可参与讨论,去登陆

1回答

问题1
LiveData设计是利用了页面生命周期感知能力,能够在宿主生命周期变化时,把LiveData最新的数据分发给注册进来的observer观察者。默认情况下,Activity A.  Activity B是没办法利用LiveData做到跨页面(跨Activity )的数据分发的,课程中为了解决这个问题,实现了HiLiveDataBus。允许跨页面(跨Activity )分发消息。

问题2
在实现HiLiveDataBus的时候,当初为了让LiveData能够自行remove掉,是监听了observer宿主的生命周期,在onDestroy时主动把LiveData移除了,但这给粘性事件带来了问题,问题就是Activity A先发消息,进入Activity B,此时Activity B能够收到消息,但是HiLiveDataBus监听了Activity B宿主生命周期,当Activity B销毁时,LiveData也一并被移除了。此时再进入Activity C则无法收到粘性消息了。
为了解决该问题,可以把对宿主生命周期的监听去除掉,由分发消息的页面选择何时移除LiveData实例。

  • 默小铭 提问者 #1

    问题二

    之前没写代码验证,后面自己写代码验证过,实际不会出现说无法收到粘性消息的问题


    我代码简单说下,不贴上来了,写了4个Activity,ABCD

    A  LiveDataBus.with<String>("StickyDataNext").setStickyData("发送一条粘性事件")  跳转到B (不finish)

    B接受粘性事件

    B  LiveDataBus.with<String>("StickyDataNext").setStickyData("发送一条粘性事件")  跳转到C (finish)

    C接受粘性事件

    C  LiveDataBus.with<String>("StickyDataNext").setStickyData("发送一条粘性事件")  跳转到D (finish)

    D接受粘性事件

    A->B  B正常收到事件

    B->C 正常收到事件(打日志,日志是C先收到事件,B再onDestory()的),所以没问题

    C->D 正常收到事件(虽然说我们代码移除了,但C->D发送,再用with发送,不是相当于又创建了一个新的LiveData,只是ebentName刚好和之前的一样罢了,所以没有问题)

    if (event == Lifecycle.Event.ON_DESTROY) {

                        Log.e("跨页面测试", "$event  ${source.javaClass.simpleName}")

                        eventMap.remove(eventName)

                    }


    测试完,感觉就像我们平常页面跳转,使用intent一个一个页面传递数据一样,不会有影响



    2021-08-04 20:52:56
  • 默小铭 提问者 #2

    同时问题一,我看到官方文档有个LiveData扩展,使用单例就能共享LiveData使用了,也相当于实现事件总线了

    2021-08-04 20:54:43
  • LovelyChubby 回复 提问者 默小铭 #3

    一个LiveData做成单例,可以也是可以,但是一个LiveData只能发送一种类型的数据耶

    2021-08-04 22:03:46
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师