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

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

https://medium.com/androiddevelopers/jetpack-compose-strong-skipping-mode-explained-cbdb2aa4b900

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

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

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

```kotlin
@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の変更にはなっていないため。

```kotlin
@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://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/c935a501-8ebf-8dd6-2490-0730decad878.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される！**

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