Jetpack Composeをアップデートしたらバグったけどなんかよくわからん方法でバグが発生しなくなった話
起こった問題
ライブラリやKotlinのバージョンが古くなっていたので一気に最新(1.4.3 → 1.5.4)までアップデートしました。(去年対応してました)
こういったことは前職まで含めいつもやっていたので、不安はありつつも問題はないだろうと楽観視していました。
ところが、そのリグレッションテストで問題が発生しました。
特定の端末で1画面で全てのタップが左上の「×」ボタンに判定が吸われており、どこをタップしても画面が閉じるようになってしまっていました。
切り分け
このリグレッションテストにはライブラリなどのバージョンアップの他にもDagger Hilt対応やその他いくつかの修正が入っていたので、まずは原因となった変更の特定を行いました。
コミットをRevertしたり、developをベースにcherry-pickしたり、コミットにcheckoutしたりした結果Composeのバージョンアップが原因なのがほぼほぼ確実だろうとなりました(コンフリクトが起きたりした結果これだけで1週間)。
そしてその場合、おそらくどこかでJetpack Composeにバグが入り込んだのだろうという結論になりました。
Jetpack Composeは重要なライブラリなので、このバグの対応のためにバージョンを固定する(バージョンアップしない)ということはできません。しかし、このバグを放置するということもビジネス上できませんでした。
なので、なんとかしてアップデート後もバグが起きない方法を探すしかありませんでした。
なぜか解決した方法
バグが起きる条件を色々探した結果、タップしていないRowの1番最初のImageのModifier.clickableの内容が呼ばれているのがわかりました。
Row(modifier = Modifier) {
Box(modifier = Modifier) {
Image(
painter = painterResource(id = R.drawable.icon_slideshow_close),
contentDescription = null,
contentScale = ContentScale.None,
modifier = Modifier
.size(48.dp)
.clickable(onClick = onScreenClosed),
)
}
// なんやかんやありーの
}
そのため
1. 該当機種でこのImageを表示しないようにする
2. Modifier.clickableが設定されていないImageを追加する
という策で対応できることがわかりました。
最終的には2の方法を使って、解決することにしました。
2で解決するとは言っても、表示が目に見えて変わると困るので、1dpかつ透明度を0%にしています。
0dpじゃないのは、それだと何故か不具合が起きるためです。(謎)
結果的にこうなりました。
Row {
// 実質表示されないImage関数
Image(
painter = painterResource(id = R.drawable.icon_slideshow_close),
contentDescription = null,
alpha = 0f,
modifier = Modifier.size(1.dp),
)
Image(
painter = painterResource(id = R.drawable.icon_slideshow_close),
contentDescription = null,
contentScale = ContentScale.None,
modifier = Modifier
.size(48.dp)
.clickableOnce(onClick = onScreenClosed),
)
}
終わり
終始なんでこうなるのかがわからない不具合でした。
もし、仮説でもいいので理由が思いつく人は教えてもらえると嬉しいです。