V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ukyoo
V2EX  ›  Android

有用 AAC 的旁友吗,有个 LiveData 的问题想请教

  •  
  •   ukyoo · 2019-07-30 18:15:04 +08:00 · 9555 次点击
    这是一个创建于 1925 天前的主题,其中的信息可能已经有所发展或是发生改变。
    假设我当前使用 RxJava 的 Flowable 作为数据源, 我应当在 Repository 里就把 Flowable 转换成 LiveData 返回, 还是在 ViewModel 的 Flowable.subscribe( )里调用 LiveData#setValue()呢, 哪个更合适呢.
    如果是 Repository 返回, 那 ViewModel 里的 val LiveData 又无法指向新的 LiveData 对象,如果用 Transformations.switchMap(sourceLiveData)处理又不是每次都能有输入参数来给你观察的,比如我点击 N 次.

    如果是后者,感觉加工 LiveData 的过程又不应该交给 ViewModel 来处理.
    7 条回复    2019-10-18 13:36:58 +08:00
    2bab
        1
    2bab  
       2019-08-02 09:12:31 +08:00
    后者,因为:

    1. LiveData 就是真实值的包装,长期可观察的对象,确实如你所言我觉得不可以也不应该不断指向新的对象;
    2. LiveData 是和 Android Framework 本身有关联的(或者说和 LifeCycle Framework ),而 Repository 层面其实是更加底层、通用层面,可以不做关心,这也是你为什么用更重量级更通用的 Rx Framework 在这一层来处理逻辑和数据的原因吧,故放在 ViewModel 挺合理,楼主可以说一下为什么感觉不合理~
    ukyoo
        2
    ukyoo  
    OP
       2019-08-02 09:42:25 +08:00
    @2bab Hi, 这么做不是不可以.我是这么想的, 既然已经用了 Repository,在 ViewModel 只是应该调用 Repo 来直接获取加工好的数据, ViewModel 应该只负责向 View 层提供 LiveData.
    参考官方的 arch_browse_sample 里, 成功失败的状态和数据都是在 Repo 里包装的,ViewModel 里直接通过 Repo 获取 LiveData. 但是官方的例子大量使用了 Transformations.flatMap(sourceLiveData), 在实际开发中不可能一直有 sourceLivedata 来观测, 比如我只是点击一下这时候是没有输入参数的,这时就不能借助 flatMap..所以我在 arch_sample 下提了个 issue:
    https://github.com/googlesamples/android-architecture-components/issues/686

    别的帖子里大佬的思路: 把 ViewModel 里 LiveData 的引用传递给 Repo
    https://i.loli.net/2019/07/30/5d40467b25b8b95582.png
    2bab
        3
    2bab  
       2019-08-02 10:34:34 +08:00
    @ukyoo 我觉得你说的很具体了,那可以讨论一下几个具体的点:

    1. ",在 ViewModel 只是应该调用 Repo 来直接获取加工好的数据":这点可以这样考虑,比如同样一个购物车信息的 Repo 可以被多个地方调用(甚至是同一个 Repo 的同一个 API ),但展示出来的方式可能略有不同,所以你可能会分别在 ViewModel 内做一些针对不同 UI 元素的数据后置处理(比如把给每个标题加上 1234 的顺序索引),我觉得 Repo 不需要承担 100% 的源数据处理工作,更多的是做好偏下层的通用性处理,ViewModel 可以有一点点真正对 "View" 的 "Model" 的处理;
    2. "把 ViewModel 里 LiveData 的引用传递给 Repo":正如前面讨论的,LiveData 更多是要在 ViewModel 和 View 这边去发挥作用,而 Repo 本身是可以被更多地方使用,例如几个 Repo 之间可以互相调用,也即现在比较普遍的模块化框架下几个模块之间的功能互相 invoke,这种情况下我们并不需要 LiveData,而是使用如题所说的 Rx,如果要做这个方案,那么就得把大量的 Repo 里的 API 提供两套接口,一套没有 LiveData 一套有,不过也不能说不是一种解法吧。
    ukyoo
        4
    ukyoo  
    OP
       2019-08-02 19:21:35 +08:00
    @2bab 嗯哈怎么写都可以...只是想看看官方的最佳实践, "advanced" browseSample 还是不够
    colaman
        5
    colaman  
       2019-08-08 10:22:46 +08:00
    livedata 实际上更应该是对于结果 /状态的发射,而不是像我们以前的一个 rxjava 流一样做各种变换操作,官方有 livedata 和 Observable 的转换方法,但是实际上不适用于 RxJava,如果是用原本的 Retrofit+Rxjava 的 方式来写,确实更应该在数据变换完之后用 livedata 发射出去,只是这样看起来有点多余。如果用 kotlin 协程来写的话就显得比较简洁有效了
    ukyoo
        6
    ukyoo  
    OP
       2019-08-08 11:24:25 +08:00
    @colaman LiveDataReactiveStreams 没法处理 rxjava 的 onError, 这个不满足我现在的需求. 我没用过协程,请问协程怎么处理异常啊, 用 CoroutineExceptionHandler 吗?
    colaman
        7
    colaman  
       2019-10-18 13:36:58 +08:00
    @ukyoo 协程按照官方的处理是 try catch 这种最基础的写法,但是可以自己封装一下代码块或者 CoroutineExceptionHandler 都是可以的,看自己喜欢哪种思路。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3356 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 11:34 · PVG 19:34 · LAX 03:34 · JFK 06:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.