RiverpodのStreamProviderを使ってPushNotificationを実装してみた

はじめに

エキサイト株式会社の高野です。エキサイトホールディングス Advent Calendar 2023の3日目を担当させていただきます。

今回はFlutterにおけるRiverpodのStreamProviderを使ってPushNotificationを実装した話です。

動作環境

Flutter: 3.13.4

hooks_riverpod: 2.3.4

riverpod_annotation: 2.0.4

rxdart: 0.27.1

実装方法

まず始めに実際のコードを載せておきます。

@Riverpod(keepAlive: true)
Stream<PushNotificationData?> pushNotificationStream(
  PushNotificationStreamRef ref,
) async* {
  final event = await ref.watch(pushNotificationOnMessageProvider.future);
  yield ref.watch(pushNotificationProvider).onOpenMessage(event.data);
}

@Riverpod(keepAlive: true)
Stream<RemoteMessage> pushNotificationOnMessage(
  PushNotificationOnMessageRef ref,
) {
  return Rx.merge([
    Stream.fromFuture(FirebaseMessaging.instance.getInitialMessage())
        .whereNotNull(),
    FirebaseMessaging.onMessage,
    FirebaseMessaging.onMessageOpenedApp,
  ]);
}

まず一つ目のポイントとしているのは、Pushの監視状態は途中で切れてほしくないのでkeepAliveをtrueにしています。 次に以下の部分です。

  return Rx.merge([
    Stream.fromFuture(FirebaseMessaging.instance.getInitialMessage())
        .whereNotNull(),
    FirebaseMessaging.onMessage,
    FirebaseMessaging.onMessageOpenedApp,
  ]);

初回の通知確認、アプリを開いている時に通知を開いた場合、アプリを閉じている時に通知を開いた場合という3つを区別なく処理をします。

こちらの各Streamを同一StreamにするProviderを作成しました。

  final event = await ref.watch(pushNotificationOnMessageProvider.future);
  yield ref.watch(pushNotificationProvider).onOpenMessage(event.data);

そして ref.watch を使用して流れてくる値を監視し、整形してまたStreamとして流します。

ref.listen(pushNotificationStreamProvider, (_, asyncValue) {
      final data = asyncValue.valueOrNull;
      if (data == null) {
        return;
      }
      // ここに遷移処理等を書く
}

最後にこのProviderをlistenしてあげ、Push通知を開いた際の処理を書きます。

意外と行数も増えることなく書くことができました。

最後に

エキサイトではエンジニアを随時募集しています。 興味がありましたらお気軽にご連絡いただければ幸いです。

www.wantedly.com