アウトプッツ

育児・おでかけ・アプリ開発

【Jetpack Compose】LaunchedEffectは若干のオーバーヘッドがあり、1フレーム遅れて実行される

ふと、DroidKaigi 2023の配信動画を見ていたら、とても意外だったところがあったので残しておく。

(本当はQiitaにでもまとめてみようかと思ったけど、うまくまとめられそうにないのでブログに雑な感じで。)

 

タイトルにある通り「LaunchedEffectは若干のオーバーヘッドがあり、1フレーム遅れて実行される」というのが意外だった。

 

発表は「Jetpack Compose の Side-effect を使いこなす」で、誰もが一度はmediumでお世話になっているだろうSTAR_ZEROさんの発表である。

スライドでは「若干のオーバーヘッド」としか書いてないが、動画の方では「確か1フレーム遅れて実行されるのかな?」という発言もある。

 

スライド(P.59)

speakerdeck.com

 

動画

youtu.be

 

まぁ普通だったらさらっと「ふーん、そうなんだぁ」と流してしまうポイントかと思うが、自分の場合、ちょうど LaunchedEffect を使った実装で処理にラグがあり、どうしたもんかと悩んでいたところだったので、この発表・発言を聞いて「そうだったのか…!」となったのである。

少し調べてみた

LaunchedEffect のオーバーヘッドについて言及されているものを調べてみたら、たしかに同じようなことを言っているXの投稿などがあるようだった。

 

jetc.dev

実装を少し追ってみる

fun LaunchedEffect(
    key1: Any?,
    block: suspend CoroutineScope.() -> Unit
) {
    val applyContext = currentComposer.applyCoroutineContext
    remember(key1) { LaunchedEffectImpl(applyContext, block) }
}

 

currentComposer.applyCoroutineContext が使われている。

 

おもむろにログ出力してみる。

[androidx.compose.ui.platform.MotionDurationScaleImpl@2b1334b, androidx.compose.runtime.BroadcastFrameClock@a15e128, JobImpl{Active}@2db3e41, AndroidUiDispatcher@b977fe6]

 

よくわからんが、AndroidUiDispatcher を見てみる。

androidx.tech

 

Choreographer を使ってフレーム毎に処理してるっぽいことがわかった。(雰囲気理解)

まとめ

- 「LaunchedEffectは若干のオーバーヘッドがあり、1フレーム遅れて実行される」はたしかにそうなってるっぽい。

- 発表でしかわからないこともあるので、発表を聞くのは大事である。