Compose - 全局变量 CompositionLocal

CompositionLocal提供了一种在JetpackCompose中管理全局状态的方式,它允许值在组件树中局部生效,避免了传统全局变量的副作用。通过CompositionLocal,开发者可以修改值并控制其影响范围,提高代码的可复用性和组合性。CompositionLocalOf用于创建实例,current属性用于获取值,而CompositionLocalProvider则用于提供作用域内的新值。

一、概念

显式传参

局部变量,中间层或底层要使用通过函数形参层层传递,嵌套深耦合高不利于组合的复用。

隐式传参全局变量,中间层或底层能直接获取,一处更改处处新值。

二、CompositionLocal

        通常情况下,数据通过形参传递给函数,可组合函数是层层嵌套的形式,但对于广泛使用的常用数据(例如颜色形状...)层层往下传递会很麻烦,而使用全局变量的话,当需要对该值修改后使用,一处修改会导致所有调用处都是新值,即便赋值给局部变量再使用,更底层函数想使用该局部变量,不是再层层传递下去就是又需要用局部变量去接收,还做不到层层引用相同的变量名(污染中间函数)。

        使用 CompositionLocal 包装的全局变量,对于值的修改既可以全局生效,也可以只在 CompositionLocalProvider 提供的作用域内局部有效(函数穿透功能:在作用域内就能生效,无关作用域内的函数层级),出了该作用域失效,不会影响其它调用处。注意:变量名需要以“local” 开头,top-level需要以“Local”开头。

compositionLocalOf()

public fun <T> compositionLocalOf(
    policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy(),
    defaultFactory: () -> T,
): ProvidableCompositionLocal<T> 

值更改后,只有直接读取该值的组合项会重组(CompositionLocalProvider提供的作用域中,读取的是修改后的,并未直接读取,不会重组)。

staticCompositionLocalOf()

public fun <T> staticCompositionLocalOf(

    defaultFactory: () -> T

): ProvidableCompositionLocal<T>

值更改后,所有引用的地方都会重组(不管是直接读取该值的组合项,还是CompositionLocalProvider提供的作用域),当值几乎不会被更改的时候使用性能更高,因为上面那个会追踪值的读取。

CompositionLocalProvider提供作用域,修改的值只在该作用域内有效。
provides用来修改值,可以是函数调用,推荐是中缀调用。
current取出的值为最近外层所修改的值,外层所有嵌套不存在修改则为默认值。
//编译器会提示变量名应该以“Local”为前缀
//不想提供或无法提供有意义的默认值,可以直接抛异常。
val LocalUser = compositionLocalOf { User("张三") }
//val LocalUser = compositionLocalOf { error("LocalUser没有提供值!") } 

@Composable
fun Show() {
    Column {
        //CompositionLocalProvider函数提供作用域,provides中缀表达式提供修改,current取出当前值
        CompositionLocalProvider(LocalUser provides User("李四")) {
            val newUser = LocalUser.current //这里取出的值是修改过的“李四”
        }
        val user = LocalUser.current    //这里取出的值是未修改过的“张三”
        val color = MaterialTheme.colors.primary    //这里取出的值是MaterialDesign提供的
        val context = LocalContext.current.resources.getString(R.string.app_name)    //获取上下文和资源
        val app = LocalContext.current.applicationContext as MyApplication //获取自定义的 Application
    }
}

Duplicate class androidx.navigation.compose.BackStackEntryIdViewModel found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposableSingletons$ComposeNavigatorKt found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposableSingletons$ComposeNavigatorKt$lambda$127448943$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposableSingletons$DialogNavigatorKt found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposableSingletons$DialogNavigatorKt$lambda$-1092249270$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposeNavGraphNavigator found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposeNavGraphNavigator$ComposeNavGraph found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposeNavigator found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposeNavigator$Companion found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposeNavigator$Destination found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposeNavigator$Destination$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.ComposeNavigatorDestinationBuilder found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogHostKt found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogHostKt$DialogHost$1$2 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogHostKt$DialogHost$1$2$2 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogHostKt$DialogHost$1$2$invoke$lambda$2$lambda$1$$inlined$onDispose$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogHostKt$DialogHost$2$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogHostKt$PopulateVisibleList$lambda$12$lambda$11$lambda$10$$inlined$onDispose$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogNavigator found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogNavigator$Companion found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogNavigator$Destination found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.DialogNavigatorDestinationBuilder found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavBackStackEntryProviderKt found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavGraphBuilderKt found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavGraphBuilderKt$composable$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostControllerKt found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostControllerKt__NavHostControllerKt found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$25$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$25$1$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$28$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$29$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$29$1$1$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$32 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$32$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$33$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$lambda$48$lambda$47$$inlined$onDispose$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.NavHostKt$NavHost$lambda$69$lambda$68$$inlined$onDispose$1 found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Duplicate class androidx.navigation.compose.internal.WeakReference found in modules navigation-compose-jvmstubs-2.9.0.jar -> navigation-compose-jvmstubs-2.9.0 (androidx.navigation:navigation-compose-jvmstubs:2.9.0) and navigation-compose-release.aar -> navigation-compose-release-runtime (androidx.navigation:navigation-compose-android:2.9.0) Learn how to fix dependency resolution errors at https://d.android.com/r/tools/classpath-sync-errors
05-28
### 解决 Android 项目中 `navigation-compose` 版本 2.9.0 的重复类冲突问题 在处理 Android 项目时,如果遇到类似 `Duplicate class androidx.navigation.compose.BackStackEntryIdViewModel` 的问题,通常是因为多个依赖项引入了同名的类。以下是针对该问题的专业解决方案。 #### 确保依赖版本一致性 重复类问题通常源于不同模块或库之间存在版本冲突。为了解决此问题,需要确保所有与 `navigation` 相关的依赖项使用相同的版本号。例如,在 `build.gradle` 文件中添加以下内容: ```gradle def nav_version = "2.9.0" implementation "androidx.navigation:navigation-compose:$nav_version" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version" ``` 通过统一版本号,可以避免因版本不一致导致的重复类问题[^1]。 #### 排查冲突来源 如果仍然存在重复类问题,可以通过运行以下命令来检查依赖树并定位冲突来源: ```bash ./gradlew app:dependencies ``` 此命令将输出项目的完整依赖树,帮助识别哪些依赖项引入了冲突的类。例如,如果发现某些第三方库也包含 `androidx.navigation` 的相关类,则需要排除这些冲突的依赖项[^3]。 #### 使用 `exclude` 排除重复依赖 在 Gradle 中,可以使用 `exclude` 关键字来排除特定的依赖项。例如,如果某个第三方库引入了旧版本的 `navigation-compose`,可以通过以下方式排除它: ```gradle implementation("com.some.library:some-library:1.0.0") { exclude group: 'androidx.navigation', module: 'navigation-compose' } ``` 通过这种方式,可以确保项目中只包含一个版本的 `navigation-compose`[^3]。 #### 强制指定依赖版本 如果无法直接排除冲突的依赖项,可以使用 Gradle 的强制版本策略来确保所有模块使用相同的版本。例如: ```gradle configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> if (details.requested.group == 'androidx.navigation') { details.useVersion "2.9.0" } } } ``` 此配置会强制所有 `androidx.navigation` 的依赖项使用版本 `2.9.0`,从而避免版本冲突[^2]。 #### 检查 Maven 仓库连接 如果在构建过程中遇到类似 `Could not GET 'https://maven.google.com/androidx/navigation/navigation-runtime/maven-metadata.xml'. > Connect to maven.google.com:443 [maven.google.com/172.217.24.14] failed: connect timed out` 的错误,可能是由于网络问题导致无法访问 Maven 仓库。可以尝试以下方法解决: - 确保项目中的 `repositories` 配置正确,包含 Google 的 Maven 仓库: ```gradle repositories { google() mavenCentral() } ``` - 如果网络环境受限,可以考虑使用代理或切换到国内镜像源,例如阿里云的 Maven 仓库[^2]。 --- ### 示例代码:完整的 `build.gradle` 配置 以下是一个完整的 `build.gradle` 配置示例,展示了如何解决 `navigation-compose` 的重复类问题: ```gradle plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } android { compileSdk 34 defaultConfig { applicationId "com.example.app" minSdk 21 targetSdk 34 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = '17' } } dependencies { def nav_version = "2.9.0" // Navigation Compose implementation "androidx.navigation:navigation-compose:$nav_version" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version" // Exclude conflicting dependencies implementation("com.some.library:some-library:1.0.0") { exclude group: 'androidx.navigation', module: 'navigation-compose' } // Other dependencies implementation "androidx.core:core-ktx:1.12.0" implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2" } // Force dependency versions configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> if (details.requested.group == 'androidx.navigation') { details.useVersion "2.9.0" } } } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值