問題
通知設定画面でアンインストール済みアプリが一覧に残り続けるバグがあった。クリーンアップ(更新)処理はアプリ選択画面の初期化時にしか走っておらず、「アプリの設定画面を開いたままバックグラウンドへ移動→別アプリをアンインストールして戻る」という処理を行うと削除したはずのアプリが表示されたままだった。
そこで2つの方法で対策を考えたのですが、どちらを選んだのかという設計部分の話です。
BroadcastReceiver
OS のシステムイベントを非同期で受け取る仕組み。ACTION_PACKAGE_FULLY_REMOVED というインテントを購読することでアンインストールの瞬間を検知できる。ただし正しく動かすにはaddDataScheme("package") の指定が必要で、これを忘れるとイベントが来ないまま無音で失敗する。また onCleared() での unregisterReceiver を忘れるとリークする。登録・解除を自前で管理する必要があり、得られるものに対して実装リスクが高い。
LifecycleResumeEffect(採用)
Compose のライフサイクル連携 API で、画面が前面に戻る(Resume)タイミングでコールバックを受け取れる。
2つの設計の選択
「ユーザーがアンインストール済みアプリを目にするのは必ず画面に戻ったとき」という点でLifecycleResumeEffectを採用した。バックグラウンドで即座に DB を更新しても画面に反映されるタイミングは変わらないため、どちらの方針でもユーザー体験の差はゼロになると考える。
終わりに
「どのタイミングで処理するか」ではなく「ユーザーがいつ結果を目にするか」を起点に考えると、過剰な実装を避けやすくなる。
という流れで今回は進めましたが、これが必ずしも成果というわけではないと思います。
それぞれの設計理念やコードの状況で適切に使い分けたいですね。