Jetpack ComposeにおいてUIの下位階層にデータを渡すには、Composable関数に引数を渡していくのが一般的だと思います。
引数で渡す以外の方法として、CompositionLocal
があります。
これの使い方について解説します。
注意事項
先に CompositionLocal
に関する注意事項を書いておきます。
CompositionLocal
はほとんどケースでは使わなくて良いものです。グローバル変数のように見えるため乱用するとメンテンスが難しくなったりバグを引き起こしやすくなったりする可能性があります。
一部ケースで有用なものですが、使用する際は十分に注意してください。
実装方法
例として、User情報を下位階層に渡したい場合を実装していきます。
まず compositionLocalOf
を使ってCompositionLocal
のキーを作成します。
型パラメータとして下位階層に渡したい型を指定し、引数の関数にはデフォルトの値を指定します。この例では、もし渡されてなかった場合はエラーにしています。
次に CompositionLocalProvider
を使って実際にUserの情報を提供します。
compositionLocalOf
で作ったキーに対して provides
を使って実態を渡します。分かりにくいですが、provides
はinfix関数になっていて、 ProvidedValue
を生成するようになっています。
最後に渡された値を取得します。
上のようにキーのcurrentからいつでもUserの情報が取得できるようになります。
もし、 CompositionLocalProvider
で渡してない場合は、compositionLocalOf
で指定したデフォルトが使用されますが、今回はエラーになるようにしています。
提供されてるCompositionLocal
特に意識しなくても使えるようになってる CompositionLocal
がいくつかあります。androidx.compose.ui.platform
にLocal~みたいな名前で定義されています。
https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/package-summary
よく使いそうなものでいうと、 Contextが取得できる LocalContext
や、URLを開くことができる LocalUriHandler
があります。
参考
https://developer.android.com/reference/kotlin/androidx/compose/runtime/CompositionLocal
おまけ
ぼくが思いついた便利な使い方としてはNavigation Composeと組み合わせた使い方です。
まず画面遷移のメソッドを定義したinterfaceをつくります。
CompositionLocal
のキーを作ります。
先程のNavigatorを実装したクラスをつくります。
これで準備完了です。
CompositionLocalProvider
を使って下位階層で使えるようにします。
で、あとは画面遷移したい箇所で、以下のようにするだけです。
これで引数にNavControllerを渡していかなくてもよくなります。あとは、テストを書くときにダミーのNavigator実装を提供すればテストも書きやすくなります。
AndroidDevChallengeの実装でもやっているので、こちらも参考にしてもらえると良いかもです。