在Android上使用Firebase Cloud Messaging时,通常希望将传入的推送通知通知当前Activity。推荐的一种方法是使用 LocalBroadcastManager IntentFirebaseMessagingService实现发送到Activity(StackOverflow example answer)。

但是,从版本1.1.0-alpha01(2018-12-17)开始, LocalBroadcastManager is deprecated:



尽管此类很可能会保留更长的时间,但我还是想开始清理我们的应用程序,因此我想迁移到更好的方法,然后Google真正删除旧方法。

目前,这些本地广播在我们的应用程序中具有两个主要角色:

  • 使用来自推送通知的新数据更新UI。这种工作方式是,每个关心传入推送数据的Activity都有一个广播接收器,该接收器监听适当的消息并更新其自己的 View 数据。
  • 如果服务器发送结束 session 的通知,则强制用户注销。这适用于每个 Activity 都有广播接收器实例的实例,该实例监听注销事件,结束该 Activity ,然后启动“登录” Activity 。

  • 如我所见,这些用例在两个建议的替代方案上都有问题:
  • LiveData最容易在ActivityFragment中用作ViewModel的一部分。但是,ViewModel仅应在直接处理UI的那些类中使用。从ViewModel中访问FirebaseMessagingService很难受,这从体系结构的角度来看是一个非常糟糕的主意。另外,不同的 Activity 和 fragment 具有不同的ViewModel对象,我不希望该服务需要访问它们全部。
  • 我可以使用一堆object属性创建Kotlin LiveData(又称Singleton),让FirebaseMessagingService从传入消息中更新这些LiveData对象,让Activity观察这些更改并将其复制到自己的ViewModelLiveData属性中。问题是双重的:首先,它要求我为每个数据段使用两个相同的LiveData对象,一个在ViewModel中,一个在object中;其次,它对我处理“注销事件”没有帮助,因为LiveData旨在处理更改的数据,而不是监听事件流。 (我可以使用 LiveData Event Wrapper来处理第二个问题,但是对于某些不适合这种方式的事情,这仍然感觉很糟糕。)
  • 尽管响应流(例如RxJava)可能会满足我的需要,但在过去的几个月中,我已经强制我的团队学习Kotlin,Android Databinding,Android ViewModel和许多其他新东西,我认为他们可以花更多的钱。 RxJava只是为此用途而增加的一件大事,并且我们没有计划重写整个应用程序以利用它来证明其增加的合理性。

  • 我发现的一个建议是将Kotlin Coroutines与ChannelFlow一起使用。它们可以与响应流非常相似地使用,但是(与RxJava不同)旨在与Kotlin一起使用,并且可以从Kotlin对Java的改进中受益。由于Google已经宣布他们专注于Android开发而不是Java的Kotlin,因此此选项特别具有吸引力。

    虽然在我看来这是最好的选择,但我还没有从其他人那里获得任何反馈,有关它是否有效以及这种实现是否有副作用和/或陷阱。我发现的唯一一件事是kotlinx.coroutines存储库上的open issue,它需要提供这样的应用程序示例。虽然我想贡献这样一个例子,但我认为我对它的了解还不足以创建一个很好的例子,并且我不希望我的生产应用程序成为豚鼠。我也不知道在这种情况下将显式Couroutines与Channel一起使用还是将suspendFlow一起使用是否更好(或更合适)。

    总之:
  • Kotlin协程及其相关的并发结构是处理Android ServiceActivity之间通信的好方法吗?
  • 如果可以,使用哪种Kotlin类型更合适使用ChannelFlow
  • 最佳答案

    协程并不能真正帮助将数据从一个软件组件传递到另一个软件组件。它们使用看起来好像是同步的语法来帮助处理异步工作的多个单元。那是协程的底线。它们类似于JavaScript中的async/await语法。尽管您可能使用协程从异步源访问数据,但是它并没有给您提供将这些数据代理到其他组件的任何先决条件。

    LiveData可能可以很好地满足您的需求。不要将ViewModel与LiveData混淆-它们可以解决不同的问题。尽管您正确地认为ViewModel仅应由处理UI的代码访问,但该指导方针并没有扩展到LiveData。公开一个反射(reflect)FirebaseMessagingService中当前数据的LiveData,这是合理的,以后再由ViewModel拾取,转换并传递给 View 。此LiveData可以是单例,也可以通过您选择的任何依赖项注入(inject)基础结构获得。

    请记住,LiveData实际上仅应用于管理状态更改。它不是您的应用程序可以收听的数据“流”。您将需要确保您的基础架构是基于状态的,以使其正常运行。 FCM本身不是基于状态的,但是如果您希望 View 响应来自FCM的消息,则需要在每条消息之间保留足够的上下文,以确保您的UI对新消息(或完全没有消息)做出一致的响应。 。

    10-07 19:40
    查看更多