【发布时间】:2020-01-14 23:06:03
【问题描述】:
在 Android 上使用 Firebase Cloud Messaging 时,通常需要通知当前的 Activity 传入推送通知。推荐的方法之一是使用LocalBroadcastManager 将Intent 从FirebaseMessagingService 实现发送到Activity (StackOverflow example answer)。
但是,从版本 1.1.0-alpha01 (2018-12-17) 开始,LocalBroadcastManager is deprecated:
LocalBroadcastManager 是一个应用程序范围的事件总线,并在您的应用程序中包含层违规:任何组件都可以侦听来自其他任何组件的事件。您可以将
LocalBroadcastManager的使用替换为可观察模式的其他实现,具体取决于您的用例,合适的选项可能是 LiveData 或反应流。
虽然这个类很可能会在一段时间内保持可用,但我还是想开始清理我们的应用程序,所以我想在 Google 真正删除旧方法之前迁移到更好的东西。
目前,这些本地广播在我们的应用中具有两个主要作用:
- 使用来自推送通知的新数据更新 UI。其工作方式是,每个关心传入推送数据的
Activity都有一个广播接收器,该接收器侦听适当的消息并更新其自己的视图数据。 - 如果服务器发送通知以结束会话,则强制用户注销。这适用于每个具有广播接收器实例的活动,该实例侦听注销事件、结束活动并启动登录活动。
在我看来,这些用例的两个建议的替代方案都存在问题:
-
LiveData最容易在Activity或Fragment中作为ViewModel的一部分使用。但是,ViewModel仅用于那些直接处理 UI 的类。从FirebaseMessagingService中访问ViewModel是一个丑陋的黑客,从架构的角度来看是一个非常糟糕的主意。此外,不同的活动和片段有不同的ViewModel对象,我不希望服务需要全部访问它们。 - 我可以用一堆
LiveData属性创建一个Kotlinobject(又名Singleton),让FirebaseMessagingService从传入的消息中更新那些LiveData对象,让Activity观察这些变化并将它们复制到它自己的ViewModel的LiveData属性中。这样做的问题是双重的:首先,它要求我为每条数据有两个相同的LiveData对象,一个在ViewModel中,一个在object中;其次,它对处理“注销事件”没有帮助,因为LiveData旨在处理不断变化的数据,而不是监听事件流。 (我或许可以使用LiveDataEvent Wrapper 处理第二个问题,但这仍然感觉像是对不应该以这种方式工作的东西的糟糕破解。) - 虽然 RxJava 等反应式流可能会满足我的需求,但在过去几个月里,我已经强迫我的团队学习 Kotlin、Android 数据绑定、Android ViewModel 和一堆其他新东西,但我没有不认为他们可以采取更多。 RxJava 也是为了这个用途而添加的一个大东西,我们没有计划重写整个应用程序以利用它来证明它的添加是合理的。
我发现的一个建议是将 Kotlin 协程与 Channels 或 Flows 一起使用。这些可以与反应流非常相似,但(与 RxJava 不同)旨在与 Kotlin 一起使用,并从 Kotlin 对 Java 的改进中受益。既然 Google 宣布他们将重点放在 Kotlin 进行 Android 开发而不是 Java 开发,这个选项就特别有吸引力。
虽然在我看来这似乎是最好的选择,但我没有设法从其他人那里找到任何关于它是否有效以及这种实现是否存在副作用和/或陷阱的反馈。我发现的唯一内容是kotlinx.coroutines 存储库上的open issue,它说明需要提供这样的应用程序示例。虽然我很乐意提供这样的示例,但我认为我对它的了解不足以创建一个好的示例,并且我不希望我的生产应用程序成为豚鼠。我也不知道在这种情况下使用显式 couroutines 和 Channel 还是使用 suspend 和 Flow 是否更好(或更合适)。
总结:
- Kotlin 协程及其关联的并发结构是处理 Android
Service和Activity之间通信的好方法吗? - 如果是,哪种 Kotlin 类型更适合使用,
Channel或Flow?
【问题讨论】:
-
有一个名为 EventBus 的库。看看。我个人从未使用过它,但我认为它可以满足您的要求。它也很小,不要使用
BroadcastReceiver -
@ManoharReddy 我不想使用 EventBus,因为首先我想看看现有的语言功能是否能满足我的需求。这就是这个问题的重点。
-
@MosheKatz 您决定采用什么解决方案?与频道有关的东西?你能发布你的想法吗,我也有类似的问题
-
@11m0 我还没有时间回到这个话题。当我这样做时,我会发布答案。
-
@xuiqzy 我还没有时间解决这个问题,因为旧方法仍然有效。当我可以这样做时,我会发布我自己的答案。使用此问题上的“关注”按钮可收到后续帖子的通知。
标签: android firebase kotlin kotlin-coroutines