CompositionLocalはシステムにより提供されているものがあります。
プログラミングに有益で利用頻度の高いものが用意されています。例えば、LocalContextやLocalConfigurationなどです。
※環境:Android Studio Giraffe | 2022.3.1 Patch 1
Kotlin 1.8.10
Compose Compiler 1.4.3
CompositionLocalのリスト
システム提供のCompositionLocalは、パッケージandroidx.compose.ui.platform以下に定義されています。
Android Studioのエディターを用いれば、補完機能(Ctrl+SPACE)がリストを表示してくれるので便利です。
※エディタで「androidx.compose.ui.platform.Local」と打ち込んだ場合
また、androidx.compose.ui.platformのドキュメントに、簡単な説明が掲載されています。
状態の保持
状態の保持はMainActivity#setContent()を実行した際に自動的に行われます。ですので、ユーザは何もすることなく、システム提供のCompositionLocalが利用可能です。
class MainActivity : ComponentActivity() { @SuppressLint("CoroutineCreationDuringComposition", "UnrememberedMutableState") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // ← システム提供のCompositionLocalの状態を保持 androidx.compose.ui.platform.LocalContext MyApplicationTheme { // アプリのコンテンツ } } } }
内部ではProvideAndroidCompositionLocals関数が実行されています。
@Composable @OptIn(ExperimentalComposeUiApi::class) internal fun ProvideAndroidCompositionLocals( owner: AndroidComposeView, content: @Composable () -> Unit ) { val view = owner val context = view.context var configuration by remember { mutableStateOf( context.resources.configuration, neverEqualPolicy() ) } ... val imageVectorCache = obtainImageVectorCache(context, configuration) CompositionLocalProvider( LocalConfiguration provides configuration, LocalContext provides context, LocalLifecycleOwner provides viewTreeOwners.lifecycleOwner, LocalSavedStateRegistryOwner provides viewTreeOwners.savedStateRegistryOwner, LocalSaveableStateRegistry provides saveableStateRegistry, LocalView provides owner.view, LocalImageVectorCache provides imageVectorCache ) { ProvideCommonCompositionLocals( owner = owner, uriHandler = uriHandler, content = content ) } }
@OptIn(ExperimentalTextApi::class) @ExperimentalComposeUiApi @Composable internal fun ProvideCommonCompositionLocals( owner: Owner, uriHandler: UriHandler, content: @Composable () -> Unit ) { CompositionLocalProvider( LocalAccessibilityManager provides owner.accessibilityManager, LocalAutofill provides owner.autofill, LocalAutofillTree provides owner.autofillTree, LocalClipboardManager provides owner.clipboardManager, LocalDensity provides owner.density, LocalFocusManager provides owner.focusOwner, @Suppress("DEPRECATION") LocalFontLoader providesDefault @Suppress("DEPRECATION") owner.fontLoader, LocalFontFamilyResolver providesDefault owner.fontFamilyResolver, LocalHapticFeedback provides owner.hapticFeedBack, LocalInputModeManager provides owner.inputModeManager, LocalLayoutDirection provides owner.layoutDirection, LocalTextInputService provides owner.textInputService, LocalPlatformTextInputPluginRegistry provides owner.platformTextInputPluginRegistry, LocalTextToolbar provides owner.textToolbar, LocalUriHandler provides uriHandler, LocalViewConfiguration provides owner.viewConfiguration, LocalWindowInfo provides owner.windowInfo, LocalPointerIconService provides owner.pointerIconService, content = content ) }
※状態の保持については「Jetpack Compose:UIツリーにローカルな変数の確保(CompositionLocal)」を参照
StaticとDynamic
キーの定義をみると、LocalConfigurationのみDynamic側であり、その他はStatic側である事に注意してください。
ユーザー定義のCompositionLocalと再Composeの範囲に違いが出ます。
: : /** * The Android [Configuration]. The [Configuration] is useful for determining how to organize the * UI. */ val LocalConfiguration = compositionLocalOf<Configuration>( neverEqualPolicy() ) { noLocalProvidedFor("LocalConfiguration") } /** * Provides a [Context] that can be used by Android applications. */ val LocalContext = staticCompositionLocalOf<Context> { noLocalProvidedFor("LocalContext") } : :
※Dynamic側とStatic側の違いは「Jetpack Compose:staticCompositionLocalOfの違い」を参照
例:LocalContext
サンプルはStringリソースから文字列を取得して、地域に適した言語で表示する例です。
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">LocalContext Sample</string> <string name="greeting">こんにちは アンドロイド!</string> </resources>
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MyApplicationTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { Greeting() } } } } } @Composable fun Greeting(modifier: Modifier = Modifier) { val _text = LocalContext.current.resources.getString(R.string.greeting) Text( text = _text, modifier = modifier ) }
※注意:端末のLanguagesを「日本語(日本)」にしてください。
例:LocalConfiguration
Configurationは端末の構成の変更を管理するシステムです。
構成の変更とは、例えば端末の回転(Orientation:Landscope⇔Portrait)などです。
通常、構成の変更が行われると、Activityの再作成が行われます。つまり、旧構成のActivityインスタンスは閉じられ、新構成のActivityインスタンスが作成されます。
ただし、ユーザによりActivtyの再作成の抑止(AndoridManifest.xmkへ追記)が可能です。
サンプルは端末の回転が行わた時にActivityの再作成を抑止して、Orientationが変わったことによる画面の表示切替をプログラムに委ねる例です。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application ...> <activity android:name=".MainActivity" android:configChanges="orientation" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.MyApplication"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MyApplicationTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { ElementA() } } } } } @Composable fun ElementA() { ElementB() } @Composable fun ElementB() { ElementC() } @Composable fun ElementC() { val _text = when(LocalConfiguration.current.orientation) { Configuration.ORIENTATION_LANDSCAPE -> "Landscape !" Configuration.ORIENTATION_PORTRAIT -> "Portrait !" else -> "Unknown !" } Text(text = _text) }
※注意:端末のAuto-rotateをOnにしてください。
関連記事: