Androidで Firebase Cloud Messaging を使用する場合、多くの場合、現在のActivity
に着信プッシュ通知を通知することが望まれます。これを行うための推奨される方法の1つは、 LocalBroadcastManager
を使用してIntent
をFirebaseMessagingService
実装からActivity
に送信することです( StackOverflowの例の回答 )。
ただし、バージョン1.1.0-alpha01(2018-12-17)以降、 LocalBroadcastManager
は非推奨 :
LocalBroadcastManagerはアプリケーション全体のイベントバスであり、アプリのレイヤー違反を受け入れます。どのコンポーネントも他のコンポーネントからのイベントをリッスンする可能性があります。ユースケースに応じて、
LocalBroadcastManager
の使用を観察可能なパターンの他の実装に置き換えることができます。適切なオプションは LiveData またはリアクティブストリームです。
このクラスはしばらくの間利用できる可能性が高いですが、とにかくアプリケーションのクリーンアップを開始したいので、Googleが古い方法を実際に削除する前に、より良いものに移行したいと思います。
現在、これらのローカルブロードキャストには、アプリで2つの主要な役割があります。
Activity
が、適切なメッセージをリッスンし、独自のビューデータを更新するブロードキャストレシーバーを持っていることです。私が見ているように、これらのユースケースには、提案されている代替案の両方に問題があります。
LiveData
は、Activity
またはFragment
でViewModel
の一部として使用するのが最も簡単です。ただし、ViewModel
は、UIを直接処理するクラスからの使用のみを目的としています。 ViewModel
内からFirebaseMessagingService
にアクセスすることは醜いハックが必要であり、アーキテクチャーの観点からは非常に悪い考えです。また、異なるアクティビティとフラグメントには異なるViewModel
オブジェクトがあり、サービスがそれらすべてにアクセスする必要はありません。object
プロパティを使用してKotlin LiveData
(別名シングルトン)を作成し、FirebaseMessagingService
で受信メッセージからこれらのLiveData
オブジェクトを更新し、Activity
でこれらの変更を監視して独自のViewModel
のLiveData
プロパティにコピーすることができます。これに関する問題は2つあります。最初に、データの各部分に対して2つの同一のLiveData
オブジェクトが必要です。1つはViewModel
にあり、もう1つはobject
にあります。 2番目に、LiveData
はイベントのストリームをリッスンするのではなく、データの変更を処理することを目的としているため、「ログアウトイベント」の処理には役立ちません。 (これで LiveData
Event Wrapper を使用して2番目の問題を処理できるかもしれませんが、それでも、この方法で動作することを意図していない何かに対する悪いハックのように感じます。)私が見つけた1つの提案は、Channel
sまたはFlow
sでKotlinコルーチンを使用することでした。これらは、リアクティブストリームと非常によく似た方法で使用できますが、(RxJavaとは異なり)Kotlinで使用することを意図しており、Javaに対するKotlinの改善の恩恵を受けています。 GoogleがAndroid開発のためにKotlinに焦点を当てていると発表したため、このオプションは特に魅力的です。
これが最良の選択肢のように思えますが、それが機能するかどうか、およびそのような実装に副作用や落とし穴があるかどうかについて他の人からのフィードバックを見つけることができませんでした。私が見つけた唯一のものは、このようなアプリケーションの例を提供する必要性について、kotlinx.coroutines
リポジトリの 未解決の問題 でした。私はそのような例を提供したいのですが、良い例を作成するのに十分な知識がないと思います。本番用アプリをモルモットにしたくありません。また、この場合、Channel
で明示的なコルーチンを使用するのが良いのか、suspend
でFlow
を使用するのが良いのか(または適切であるのか)もわかりません。
要約すれば:
Service
とActivity
の間の通信を処理する良い方法ですか?Channel
またはFlow
?コルーチンは、あるソフトウェアコンポーネントから別のソフトウェアコンポーネントへのデータの受け渡しにはあまり役立ちません。これらは、同期のように見える構文を使用して、非同期作業の複数のユニットを処理するのに役立ちます。それがコルーチンの一番下の行です。これらは、JavaScriptの非同期/待機構文に類似しています。コルーチンを使用して非同期ソースのデータにアクセスすることもできますが、そのデータを他のコンポーネントにプロキシする権限はありません。
LiveDataは、おそらくあなたがやろうとしていることに対してうまく機能します。 ViewModelとLiveDataを混同しないでください。さまざまな問題が解決されます。 ViewModelはUIを処理するコードによってのみアクセスされる必要があることは正しいが、そのガイドラインはLiveDataに拡張されない。後でViewModelによって取得され、変換されてビューに渡されるFirebaseMessagingServiceからの現在のデータを反映するLiveDataを公開することは完全に合理的です。このLiveDataはシングルトンにすることも、選択した依存関係注入インフラストラクチャを介して取得することもできます。
LiveDataは実際には状態の変化を管理するためだけに使用されることになっていることに注意してください。これは、アプリがリッスンできるデータの「ストリーム」ではありません。これがうまく機能するためには、インフラストラクチャが状態ベースであることを確認する必要があります。 FCM自体は状態ベースではありませんが、ビューがFCMからのメッセージに応答するようにする場合は、UIが新しいメッセージに一貫して応答するように(またはメッセージがまったくない場合)、各メッセージ間で十分なコンテキストを保持する必要があります。 。