1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Android】Navigation Compose + dropUnlessResumed ダイアログ閉じた後にタップ出来ない場合がある

Posted at

TL;DR

androidx.navigation:navigation-compose 2.8.5 〜 2.9.1 に由来するライフサイクル管理のバグ。2.9.2 以降にアップデートすれば解決する。

バグの修正

エントリの上のダイアログが閉じられたときにエントリが再開されない(Resumedに更新されない)問題を修正しました

問題

連続タップで意図しない画面遷移を抑制するため、Compose では dropUnlessResumed が有用です。

dropUnlessResumed は androidx.lifecycle:lifecycle-*:2.8.0 で導入されたAPIです

しかし Navigation ライブラリ側のバグでライフサイクルが Lifecycle.State.RESUMEDに正しく更新されず、正常なタップも検出されない不具合が発生し得ます。

すべての状況で不具合が発生する訳ではなく、特定条件下で表示したダイアログを閉じて前の画面に戻ると Lifecycle.State.STARTED のまま更新されないようです。

再現例

                    val navController = rememberNavController()
                    NavHost(
                        navController = navController,
                        startDestination = "screen1",
                    ) {
                        composable("screen1") {
                            MyScreen(
                                title = "Screen 1",
                                buttonLabel = "画面遷移",
                                onTap = dropUnlessResumed {
                                    // 1. 他Composableへの遷移と同時にダイアログを表示
                                    navController.navigate("screen2")
                                    navController.navigate("dialog")
                                },
                            )
                        }
                        composable("screen2") {
                            MyScreen(
                                title = "Screen 2",
                                buttonLabel = "閉じる",
                                onTap = dropUnlessResumed {
                                    // 3. タップが検出されない
                                    navController.popBackStack("screen2", true)
                                },
                            )
                        }
                        composable("dialog") {
                            MyDialog(
                                onDismiss = dropUnlessResumed {
                                    // 2. ダイアログ閉じる
                                    navController.popBackStack("dialog", true)
                                },
                            )
                        }
                    }
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?