LoginSignup
8
5

Strong skipping modeの記事を読んで知らなかったことメモ

Last updated at Posted at 2024-03-12

この記事を読みます。 基本記事に書いてあることを書いているだけです。何か誤りがあれば教えて下さい。

stable unstableとか、Listはunstableになってしまうとかをすでに知っている人向けの記事です。

  • Unstable parameterはinstance equality (===)で見る
  • stableは今までどおり equalsで見る

具体的にはこういうケースで救われる。以下だと、favoriteが変わったときに、Listがunstableなので、ArticleList()がもう一度走る(recompose)されてしまっていたが、 === での比較が変わっていないので、スキップされるようになる。

@Composable
fun ArticleList(
articles: List<Article>, // List = Unstable, Article = Stable
modifier: Modifier = Modifier // Stable
) {
  // …
}

@Composable
fun CollectionScreen(viewModel: CollectionViewModel = viewModel()) {
  var favorite by remember { mutableStateOf(false) }
  Column {
    FavoriteButton(isFavorite = favorite, onToggle = { favorite = !favorite })
    // ↓ favoriteが変わったときにlistの参照、
    // `===`が変わっていないので再実行されない
    ArticleList(viewModel.articles)
  }
}

https://medium.com/androiddevelopers/jetpack-compose-strong-skipping-mode-explained-cbdb2aa4b900 より引用

  • lambdasは自動的にrememberされる
    引数とかではなくてComposable関数に書いた val lambda = { hoge } が lambda = remember(hoge) { hoge } に書き換わる。(実は今までもremember{}されていたんだけど、キャプチャする型(ここではhoge)がstableじゃないとremember{}されてなかった)
  • これを有効にするかは1.7 Betaまでに決める

will decide whether to keep it enabled before 1.7 goes beta

Stable annotationとかは引き続き必要か?

equalsでみたい場合は必要。 管理しやすいように stability configuration files も追加している

これにスイッチしたらアプリは壊れる?

壊れないはずだけど、Compositionの数を取るようなテストをしていると壊れるかも。

1.7になると自動的にenableになるの?

compiler flagをonにしない限りは大丈夫

strong skipping前は動いて、strong skipping後は動かないコードの例はある?

以下のコードは strong skipping前は動いて、strong skipping後はボタンを押したときに期待した動作にならない。(具体的にはMyListで"Bar"が追加されない。)。listの中身にaddしても、listのMutableStateの変更にはなっていないため。

@Composable
fun MyToggle(enabled: Boolean) {}
@Composable
fun MyList(list: List<String>) {}

@Composable
fun MyScreen() {
   var list by remember { mutableStateOf(mutableListOf("Foo")) }
   var toggle by remember { mutableStateOf(false) }
   MyToggle(toggle)
   MyList(list)

   Button(
      onClick = {
         list.add("Bar") // ← !!!ここの変更が反映されない!!!
         toggle = !toggle
      }
   ) { Text("Toggle") }
}

https://medium.com/androiddevelopers/jetpack-compose-strong-skipping-mode-explained-cbdb2aa4b900 より引用

なんでStrong skipping mode始めたの?

Composeの開発中はなんでrecomposeされないんだってみんながいうと思ってたけど、逆だった。下に続く。

Strong skipping modeの代わりにIDE上でStable見れる機能出しちゃえば解決では?

この機能は出さない。

  • エッジケースなコンパイラ機能を目立たせすぎてしまう。開発者にすべてのパラメーターをstableにさせようとしてしまう。
  • lambdaがstableとして表示されてしまうのでrecomposeの問題を解決できない。(後述)

(リリースしないプロトタイプ)
image.png

https://medium.com/androiddevelopers/jetpack-compose-strong-skipping-mode-explained-cbdb2aa4b900 より引用

Composable関数の中でのdebuggerには情報を追加したよ。
ただ、なんでそもそもこの表示が必要なんだ?ってなったのが、Strong skipping modeを作る最初の理由

lambdaがstableってどういうこと?なんか再実行されるよね?

実はlambdaはstable。stableなので、lambdaはequalsのチェックを行う。ただ、このequalsはlambdaだと参照チェックになっていて、もしComposeがなにもしなければ、毎回lambdaは作り直されるので、inputがわかった判定になる。ただ、今のComposeはlambdaがstableのキャプチャをする場合だけrememberするようにしてるので参照チェックは通る。ただ、viewModelは基本的にstableじゃないんだけど、lambda = {viewModel.onClick()}とかもrememberされると開発者は期待する。Strong skipping modeではこれもrememberされる!

ただ、メモリの面でトレードオフがあるので、ゆっくりロールアウト予定だけど、今のところは良さそう。

8
5
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
8
5