Home > Back-end >  Handling multiple experimental annotations throughout an app
Handling multiple experimental annotations throughout an app

Time:12-04

I have an app that makes heavy use of experimental features for Jetpack Compose so I have to declare a bunch of annotations on the composables. Since these annotations require callers to also declare them I have ended up in a situation where I have an activity with the following code:

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)

An alternative to avoid this situation would be to use the @OptIn instead but since only one is allowed per declaration it doesn't work out for my case with multiple experimental features.

Any way… This works fine — In Kotlin 1.5.

With Kotlin 1.6 I am getting a compilation error:

Opt-in requirement marker annotation on override requires the same marker on base declaration

But the base declaration is in the standard API that I cannot change. How can I make this compile (and work as before)?

CodePudding user response:

I got tired of my code being polluted by all those annotations. The easiest way to get rid of them and have your code compile is just add this to your top build.gradle file - It's not exhaustive. Just add more compiler arguments for each annotation you need:

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"
            ]
        }
    }
}

CodePudding user response:

In addition to @Johanns answer, here is a Kotlin DSL version (with some more annotations). It would not fit as a comment...

 tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class).all {
        kotlinOptions {
            freeCompilerArgs = freeCompilerArgs   listOf(
                // Avoid having to stutter experimental annotations all over the codebase
                "-Xuse-experimental=androidx.camera.core.ExperimentalGetImage",
                "-Xuse-experimental=androidx.compose.ExperimentalComposeApi",
                "-Xuse-experimental=androidx.compose.animation.ExperimentalAnimationApi",
                "-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=com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi",
                "-Xuse-experimental=com.google.accompanist.pager.ExperimentalPagerApi",
                "-Xuse-experimental=com.google.accompanist.permissions.ExperimentalPermissionsApi",
                "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes",
                "-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi",
                "-Xuse-experimental=kotlinx.coroutines.InternalCoroutinesApi",
                "-Xuse-experimental=kotlinx.serialization.ExperimentalSerializationApi"
            )
        }
    }
  • Related