如何将数据从 FCM 的 onMessageReceived() 发送到 Fragment?

Posted

技术标签:

【中文标题】如何将数据从 FCM 的 onMessageReceived() 发送到 Fragment?【英文标题】:How to send data from FCM's onMessageReceived() to Fragment? 【发布时间】:2020-04-21 04:22:35 【问题描述】:

我正在使用 Firebase 云消息传递在我的应用中接收数据:

class CustomFirebaseMessagingService : FirebaseMessagingService() 

    override fun onMessageReceived(msg: RemoteMessage?) 
        val data = msg?.data ?: return
        val name = data["name"] as String
        val age = data["age"]?.toIntOrNull() ?: return
        val bio = data["bio"] as String
        val img1 = data["img1"] as String
        val match = Profile(name, age, bio, img1, null, null)
        Log.d(TAG, "onMessageReceived(): $name is $age")
        val fcmViewModel = ViewModelProviders.of(this).get(FcmViewModel::class.java) // .of() only takes a fragment/activity
        FcmViewModel().match.postValue(match)
        Log.d(TAG, "Value: " + FcmViewModel().match.value.toString()) // null
        super.onMessageReceived(msg)
    

当我收到 FCM 时,我想将它传递给我的 Fragment。我尝试使用 LiveData + ViewModel,但不幸的是,postValue() 实际上并没有从服务更改 ViewModel 中的数据,因为我无法从服务实例化对 ViewModel 的引用。

class FcmViewModel : ViewModel() 

    val match: MutableLiveData<Profile> by lazy 
        MutableLiveData<Profile>()
    


class MapFragment : Fragment() 

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
            fcmViewModel.match.observe(this, Observer<Profile>  profile ->
            log("$profile.name is $profile.age") // doesn't print
        )
     

有没有更好的方法将数据从FirebaseMessagingService() 传递到我的片段,或者将数据发布到FirebaseMessagingService() 内的FcmViewModel()

【问题讨论】:

一个 hacky 解决方案是在 Application 类中包含 livedata 对象,然后您的片段可以从那里订阅,您的服务也可以从那里发布。否则我会说将视图模型中的实时数据抽象到它自己的存储库类中,视图模型和服务都可以通过一些依赖注入来引用它 【参考方案1】:

LocalBroadcastManager 标记为已弃用,现在似乎没有标准的方法来执行此操作。

然而LiveDataViewModels无关。您仍然可以使用LiveData。我会推荐他评论过的@tyczj 的解决方案。或者您可以执行以下操作。

创建一个作为小型事件总线框架的单例类。这个单例类可以有你需要的LiveData 列表,FragmentService 都可以访问 LiveData 的实例。 Service 和 Fragment 可以充当生命周期的所有者,因此您不会遇到任何问题。

下面是一个sudo代码

object Events 
    val serviceEvent: MutableLiveData<String> by lazy 
        MutableLiveData<String>()
    


class CustomFirebaseMessagingService : FirebaseMessagingService() 
    override fun onMessageReceived(msg: RemoteMessage?) 
        Events.serviceEvent.postValue(profileObj)
        super.onMessageReceived(msg)
    

class MapFragment: Fragment 

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
        Events.serviceEvent.observe(this, Observer<Profile>  profile ->
            log("$profile.name is $profile.age")
        )

您还可以创建自己的LiveData 子类,并通过覆盖onActiveonInactive 函数来控制LiveData 中的数据更新

【讨论】:

谢谢,如果应用程序在前台,那就太好了。如果应用在后台,您知道如何在我的 Fragment 中接收 FCM 通知数据吗? (不点击通知) 我不确定 FCM 是否支持这一点。您必须单击通知才能访问捆绑数据。我必须检查最新的文档。 接受答案

以上是关于如何将数据从 FCM 的 onMessageReceived() 发送到 Fragment?的主要内容,如果未能解决你的问题,请参考以下文章

如何从网络向应用发送 FCM 通知

我可以使用 FCM 云将数据从数据库发送到我的 Android 应用程序吗?

如何将数据从 java 服务类发送到 kotlin 活动类? [关闭]

如何使用 FCM 将通知从一台使用 Angular2 的计算机发送到另一台计算机

FCM - 从 Java 向我的 android 设备发送通知

FCM 上游消息传递的可靠性如何?