使用时 Firebase Cloud Messaging在 Android 上,通常希望通知当前 Activity
传入的推送通知。推荐的方法之一是使用 LocalBroadcastManager
发送 Intent
来自 FirebaseMessagingService
实现到 Activity
( StackOverflow example answer )。
但是,从 1.1.0-alpha01 (2018-12-17) 版本开始, LocalBroadcastManager
is deprecated :
LocalBroadcastManager is an application-wide event bus and embraces layer violations in your app: any component may listen events from any other. You can replace usage of
LocalBroadcastManager
with other implementation of observable pattern, depending on your usecase suitable options may be LiveData or reactive streams.
虽然这个类很可能会在一段时间内保持可用,但我还是想开始清理我们的应用程序,所以我想在 Google 真正删除旧方式之前迁移到更好的东西。
目前,这些本地广播在我们的应用中有两个主要作用:
Activity
关心传入的推送数据有一个广播接收器,它监听适当的消息并更新自己的 View 数据。 在我看来,这些用例在两个建议的替代方案中都有问题:
LiveData
在 Activity
中最容易使用或 Fragment
作为 ViewModel
的一部分.然而,ViewModel
仅用于那些直接处理 UI 的类。访问 ViewModel
来自 FirebaseMessagingService
需要一个丑陋的黑客,从架构的角度来看是一个非常糟糕的主意。另外,不同的activity和fragment有不同的ViewModel
对象,我不希望服务需要访问它们。 object
(又名单例)与一堆 LiveData
属性,有 FirebaseMessagingService
更新那些 LiveData
来自传入消息的对象,并具有 Activity
观察这些更改并将它们复制到自己的 ViewModel
中的 LiveData
属性。这样做的问题是双重的:首先,它要求我有两个相同的 LiveData
每条数据的对象,ViewModel
中的一个和一个在 object
;其次,它不能帮助我处理“注销事件”,因为 LiveData
旨在处理不断变化的数据,而不是监听事件流。 (我也许可以使用这个 LiveData
Event Wrapper 来处理第二个问题,但对于不打算以这种方式工作的东西,这仍然感觉像是一个糟糕的黑客。)我发现的一个建议是将 Kotlin 协程与
Channel
一起使用s 或 Flow
s。这些可以与响应式流非常相似地使用,但(与 RxJava 不同)旨在与 Kotlin 一起使用并受益于 Kotlin 对 Java 的改进。这个选项现在特别有吸引力,因为谷歌已经宣布他们专注于 Android 开发的 Kotlin 而不是 Java。虽然这在我看来是最好的选择,但我还没有设法从其他人那里找到任何关于它是否有效以及这种实现是否存在副作用和/或陷阱的反馈。我唯一发现的是一个 open issue在
kotlinx.coroutines
关于需要提供这样的应用程序示例的存储库。虽然我很想贡献这样一个例子,但我认为我对它的了解不足以创建一个好的例子,而且我不希望我的生产应用程序成为试验品。我也不知道将显式协程与 Channel
一起使用是否更好(或合适)或使用 suspend
与 Flow
对于这种情况。总之:
Service
和 Activity
? Channel
或 Flow
? 最佳答案
协程并不能真正帮助将数据从一个软件组件传递到另一个软件组件。它们使用看起来好像是同步的语法来帮助处理多个异步工作单元。这是协程的底线。它们类似于 JavaScript 中的 async/await 语法。虽然您可以使用协程从异步源访问数据,但它并没有为您提供任何将数据代理到其他组件的原语。
LiveData 可能适用于您要执行的操作。不要将 ViewModel 与 LiveData 混为一谈——它们解决了不同的问题。虽然您认为 ViewModel 只能由处理 UI 的代码访问是正确的,但该指南并未扩展到 LiveData。公开反射(reflect)来自 FirebaseMessagingService 的当前数据的 LiveData 是完全合理的,该数据随后由 ViewModel 获取、转换并传递给 View 。这个 LiveData 可以是一个单例,或者通过你选择的任何依赖注入(inject)基础设施获得。
请记住,LiveData 实际上只应该用于管理状态变化。它不是您的应用程序可以收听的数据“流”。您将需要确保您的基础设施是基于状态的,以使其正常运行。 FCM 本身不是基于状态的,但是如果您希望 View 响应来自 FCM 的消息,则需要在每条消息之间保留足够的上下文,以确保您的 UI 一致地响应新消息(或完全没有消息) .
关于android - 使用 Kotlin 协程替换 LocalBroadcastManager 以进行 Firebase 消息传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57917403/