9

我有一个应用程序大量使用 Jetpack Compose 的实验性功能,因此我必须在可组合项上声明一堆注释。由于这些注释要求调用者也声明它们,所以我最终遇到了一种情况,即我有一个使用以下代码的活动:

import androidx.appcompat.app.AppCompatActivity

import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.ui.ExperimentalComposeUiApi

import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.permissions.ExperimentalPermissionsApi
…

class MainActivity : AppCompatActivity() {

    @ExperimentalPermissionsApi
    @ExperimentalComposeUiApi
    @ExperimentalPagerApi
    @ExperimentalMaterialNavigationApi
    @ExperimentalMaterialApi
    override fun onCreate(savedInstanceState: Bundle?) {
        // … wiring up compose code (which propagates the experimental annotations)

避免这种情况的另一种方法是使用,@OptIn但由于每个声明只允许一个,因此它不适用于具有多个实验性功能的我的情况。

无论如何……这很好用——在 Kotlin 1.5 中。

使用 Kotlin 1.6 我收到编译错误:

覆盖上的选择加入要求标记注释需要基本声明上的相同标记

但是基本声明在我无法更改的标准 API 中。 我怎样才能使这个编译(并像以前一样工作)?

4

4 回答 4

9

我厌倦了我的代码被所有这些注释污染。摆脱它们并编译代码的最简单方法是将其添加到您的顶级 build.gradle 文件中 - 这并不详尽。只需为您需要的每个注释添加更多编译器参数:

allprojects {
    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
        kotlinOptions {
            freeCompilerArgs += [
                    "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes",
                    "-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi",
                    "-Xuse-experimental=kotlinx.coroutines.InternalCoroutinesApi",
                    "-Xuse-experimental=androidx.compose.animation.ExperimentalAnimationApi",
                    "-Xuse-experimental=androidx.compose.ExperimentalComposeApi",
                    "-Xuse-experimental=androidx.compose.material.ExperimentalMaterialApi",
                    "-Xuse-experimental=androidx.compose.runtime.ExperimentalComposeApi",
                    "-Xuse-experimental=androidx.compose.ui.ExperimentalComposeUiApi",
                    "-Xuse-experimental=coil.annotation.ExperimentalCoilApi",
                    "-Xuse-experimental=kotlinx.serialization.ExperimentalSerializationApi",
                    "-Xuse-experimental=com.google.accompanist.pager.ExperimentalPagerApi"
            ]
        }
    }
}
于 2021-12-03T16:34:13.877 回答
7

避免这种情况的另一种方法是改用@OptIn,但由于每个声明只允许一个,因此它不适用于具有多个实验性功能的我的情况。

您可以将多个实验功能用逗号分隔成@OptIn.

例如@OptIn(ExperimentalComposeUiApi::class, ExperimentalFoundationApi::class, ExperimentalMaterialApi::class)

于 2021-12-09T00:26:04.333 回答
6

Kotlin DSL 中@Johanns 答案的不被弃用的变体(以及我正在使用的一些其他注释):

弃用警告:

w: '-Xuse-experimental' 已弃用,将在未来的版本中删除,请改用 -opt-in

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class).all {
        kotlinOptions {
            freeCompilerArgs = freeCompilerArgs + listOf(
                // Avoid having to stutter experimental annotations all over the codebase
                "-Xopt-in=androidx.compose.animation.ExperimentalAnimationApi",
                "-Xopt-in=androidx.compose.material.ExperimentalMaterialApi",
                "-Xopt-in=androidx.compose.runtime.ExperimentalComposeApi",
                "-Xopt-in=androidx.compose.ui.ExperimentalComposeUiApi",
                "-Xopt-in=com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi",
                "-Xopt-in=com.google.accompanist.pager.ExperimentalPagerApi",
                "-Xopt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi",
                "-Xopt-in=kotlin.ExperimentalUnsignedTypes",
                "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
                "-Xopt-in=kotlinx.coroutines.InternalCoroutinesApi"
            )
        }
    }
于 2021-12-03T20:56:43.547 回答
4

选择加入要求 | 科特林

问题

@ExperimentalAnimationApi
@Composable
fun MyCode()

手段MyCode是实验动画api,如果你想使用MyCode,明确选择加入ExperimentalAnimationApi

@Composable
fun MyOtherCode() {
  MyCode() // ERROR!, doesn't compile and shows red underlines in IDE
}

@ExperimentalAnimationApi这通常会导致我们代码中的注释过多。不要这样做

解决方案(修复编译、IDE 警告)

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MyCode() {
  // experimental animation api usage
}

不会强制调用者添加任何注释

@Composable
fun MyOtherCode() {
  MyCode() // safe, compiles and doesn't show any errors in IDE
}

作为应用程序开发人员,我们几乎总是必须
使用@OptIn(ExperimentalAnimationApi::class)and
NOT @ExperimentalAnimationApi

除非我们的代码本身在其公共表面中公开实验性声明作为返回类型或函数参数等。

仅修复编译的解决方案

或者我们可以添加

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
  kotlinOptions {
    freeCompilerArgs = freeCompilerArgs + listOf(
      "-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
    )
  }
}

但这不会删除 IDE 下划线等。所以没那么有用。

于 2022-01-11T06:06:04.380 回答