1
bkmi 2019-09-23 13:31:49 +08:00 via Android 1
既然 ViewModel 还在,说明数据还是有效的,并不是什么旧数据。
如果你想把 ViewModel 和 FragmentA 绑定,那作用域就该用 Fragment 的 |
2
zyqf 2019-09-23 13:46:19 +08:00 via Android
其中的 LiveData 并没有随着 FragmentA 的退出而清除。
我是不是可以理解为你的需求是 FragmentA 退出要清除 LiveData ? 如果是的话,在 FragmentA 销毁阶段 postValue 空对象不就好了。 |
3
wsxyeah 2019-09-23 13:56:53 +08:00 via iPhone
类似于 BehaviorSubject
|
4
KunMinX OP |
5
KunMinX OP |
6
sanousun 2019-09-23 15:11:52 +08:00 1
美团有一篇关于 LiveDataBus 的文章,你可以看看 https://tech.meituan.com/2018/07/26/android-livedatabus.html
|
7
Gehrman 2019-09-23 17:33:09 +08:00
viewModel 里加多个缓存,跟缓存一样的无视掉?
|
8
GLee9507 2019-09-23 17:40:43 +08:00 1
我认为你是没有真正的理解 ViewModel 和 LiveData
|
9
HangoX 2019-09-23 19:23:51 +08:00
其实你直接在 ViewOnCreated 的时候 getLiveData.getValue 拿出来设置就好了,既然是一次性的东西
|
10
KunMinX OP @HangoX
就用 bus-LiveData 的方案了。 不手动编写的原因,楼上我已经讲过。 不直接用 LiveDataBus 的原因是,需要维持 通过 唯一可信源 分发状态的 开发模式,来避免不可预期、难以追溯和排查的错误。 |
11
bkmi 2019-09-23 21:44:03 +08:00 via Android
你这是把 LiveData 当 EventBus 用了啊…
|
12
KunMinX OP 我很后悔开了这个贴。
除了 6 楼的 @sanousun 同学给出了建设性的答复,其他人始终慢了好几拍。 我已经把状况讲得这么清楚了。 为避免这些离题的回复 给后来者造成困扰,这里统一回复一下: 任何技术绝非凭空存在,既然存在了,就有存在的缘由。 ViewModel 被如此设计,当初就是有考虑过 使其作为跨页面共享的存在。 当 lifeCyclerOwner 传入的是 fragment 的宿主 Activity,那么这个 ViewModel 就是被该 Activity 所持有、可以被旗下 Fragments 所共享。 共享 ViewModel 的作用多是为了跨页面的通信,例如回调、实时通信等等。 LiveData 的存在是为了确立 通过唯一可信源分发状态 的开发模式,以避免旧时候滥用 EventBus 导致的 难以追溯、数据过时 等问题。 同时在 ViewModel 或单例的配合下,它使单向依赖成为了可能。 再者它也可以规避一些生命周期问题。 这也就是为什么我选择标准化的 Jetpack MVVM 架构来完成状态管理。 除了状态管理,MVVM 同样有这个条件,甚至是更好的条件,来支持消息推送。这也就是为什么我要用 LiveData 来实现跨页面通信,而拒绝使用 EventBus。 而既然考虑到 共享 ViewModel,那么 LiveData 也理应考虑到应解除对默认 粘性设计的支持。 这个粘性设计或许在 视图控制器 重建 恢复状态时有用,在消息通信时则是个麻烦,所以我说这是个 bug,务必解决。 |
13
KunMinX OP 当然,上面我说到了 “ViewModel” 包含共享的考虑,肯定会有杠精不放过一丝添堵的机会。
首先,遇到像 8 楼这种纯粹来恶心人、不就事论事 的评论,我第一个就选择 block, 其次,我可以分享一下自己在项目中是怎么使用 ViewModel 的: 因为 ViewModel 的本职主要是状态的托管,可以托管 DataBinding 或 视图控制器 所依赖的 state, 也即这种 ViewModel 是 fragment 独享的,我会为每个 Fragment 都配一个,反正我有自己编写的自动化脚本工具,配几个 state 字段就能生成对应的 ViewModel。 第二种就是专门用于数据请求,这些我也设计成让他们被 fragment 独占。因为 ViewModel 就是设计为,你传入什么 owner,这个 ViewModel 就是被哪个 owner 所持有。而且反正就算独占,fragment 重建时这个 ViewModel 被 retain 保留了因而可以支持视图状态的恢复。 第三种就是本帖提到的这种消息通信的用法。 我就说这么多了。 |
15
maninfog 2019-09-23 22:43:49 +08:00 via iPhone 1
@GLee9507 哇 你这种人真的恶心到我😫 本来就是寻求讨论的,你有何高见倒是说出来阿,啥建设性意见没有上来就是一句别人不懂,被怼了还要继续杠,shame on you !
|
16
colaman 2019-09-23 22:44:28 +08:00
@KunMinX 我当初是自己写了一个包装类处理这个粘性问题,我是觉得这种属性 Google 应该给开发者自己决定才比较合理
|
17
Didadida 2019-09-23 22:53:12 +08:00
试试 SingleLiveEvent ?
|
18
mxalbert1996 2019-09-23 22:57:21 +08:00 via Android 1
@KunMinX 说到底就是 LiveData 不是为了你这种用途而设计的。LiveData 相当于 Rx 里的 BehaviorSubject,而你却想把它当 Observable 用。
另外解决这种问题还要用反射也太不优雅了吧。写个新类继承 MutableLiveData,覆写 observe 方法在最前面加一条 setValue(null)不就行了? |
20
KunMinX OP @colaman
是的。类似的令人头疼的问题也存在于 Navigation。 Navigation 写死了切换 fragment 必须是通过 replace,而不能使用者自己选择,所以当前对于 Navigation 态度,也是保持欣赏但观望的态度(对它的声明式编程理念比较欣赏)。 网上有给出 keep-fragment-state-Navigation 的解法,这里顺带分享一下: https://github.com/STAR-ZERO/navigation-keep-fragment-sample https://github.com/lwj1994/navigation-keep-state-fragment @mxalbert1996 反射的方式影响最小。因为目标只是 为了解决 不自动倒灌 旧数据,要是先 set Null 了,那么其他已观察的页面再想要取 liveData 临时存的数据,就莫得治了 |
21
KunMinX OP @KunMinX
笔误,应该说,要是先 set Null 了,那么其他已观察的页面 就有被迫接受一次推送 null 的风险了。(因为毕竟是 一对多的推送、共享的 ViewModel 和 liveData 的情况) 数十个页面,人工操作一定会存在疏忽、需要各种判空,所以这样其实从快速开发的角度来看,埋下的隐患要大一点。 |
22
KunMinX OP @KunMinX
唉,感觉这个答案还可以更恰当一点:observe 前 set null 一次,容易造成 其他页面 遭受容易被使用者疏忽的 被迫推送,而产生不可预期的错误。 感谢 @mxalbert1996 提出的观点,让我不断地反思 设计成 反射方式 其背后的考虑。 |
23
GLee9507 2019-09-23 23:43:33 +08:00 via Android
@maninfog 我表达了一下我的主观想法,我只是主观的认为楼主理解有误,或许楼主可以另辟蹊径分析问题发生的原因。造成大家不爽深感抱歉。
|
24
janus77 2019-09-24 00:25:59 +08:00 via iPhone
问个沾边的问题,livedata 能用做 application 全局缓存么?
|
25
DioV 2019-09-24 11:51:22 +08:00
“在消息通信时则是个麻烦,所以我说这是个 bug,务必解决。”
因为 LiveData 就不是为了解决通讯而存在的,哪里谈得上 bug... 举个不恰当的例子,就像用 Retrofit 做 gRPC 的请求,能实现但绝对不是最合适的方式。 |
26
KunMinX OP @DioV 断章取义烦不烦... MVVM 是一个整体,既然 ViewModel 被设计为支持共享作用域,那么 LiveData 就应考虑到这种跨页面通信的情况,这是官方文档自己都承认的需求。现在我就给 Google 小组留言这个问题。
|
27
KunMinX OP 楼上 @colaman 同学提到的包装类的办法,经调查,如果是我这样依然托管给 ViewModel 从而维持 唯一可信源状态分发 的话,那包装类的方式其实更合适。
如果是用作纯粹的 BUS,那可以考虑反射的方式。 这里分享一篇包装类处理的办法: https://juejin.im/post/5b2b1b2cf265da5952314b63 |
28
DioV 2019-09-24 15:23:25 +08:00
@KunMinX
戾气真重... 如果你理解下的 MVVM 必须提供这样的功能。那我是不是可以理解 Jetpack Compose 作为一套 Declarative Toolkit 而不必实现这样的需求? 当然我希望你的 Feature Request 能被官方接受。毕竟我也只是个想说说自己看法的围观群众🤷♂️ |