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)?
@ExperimentalAnimationApi
❌
This annotation means - "This is an experimental API, all users have to explicitly opt in to use". Rarely the case for application developers.
@OptIn(ExperimetalAnimationApi::class)
✅
This annotation means - "I am opting in to use an experimental api". It does not force the users of this method/class to add annotation in their code.
Opt-In Requirements | Kotlin
@ExperimentalAnimationApi
@Composable
fun MyCode()
means MyCode
is experimental animation api, if you want to use MyCode
, explicitly opt in to ExperimentalAnimationApi
@Composable
fun MyOtherCode() {
MyCode() // ERROR!, doesn't compile and shows red underlines in IDE
}
👆 is what typically causes too many @ExperimentalAnimationApi
annotations in our code. DO NOT DO THIS
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MyCode() {
// experimental animation api usage
}
👆 will NOT force the callers to add any annotations
@Composable
fun MyOtherCode() {
MyCode() // safe, compiles and doesn't show any errors in IDE
}
As app developers, we almost always have to
use @OptIn(ExperimentalAnimationApi::class)
and
NOT @ExperimentalAnimationApi
,
unless our code itself is exposing experimental declarations in it's public surface as return types or function arguments etc.
Alternatively we can add
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + listOf(
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
)
}
}
but this doesn't remove the IDE underlines etc. So 👆 is not that useful.
A non-deprecated variation of @Johanns answer in Kotlin DSL (with some other annotations that I'm using):
Deprecation warning:
w: '-Xuse-experimental' is deprecated and will be removed in a future release, please use '-opt-in' instead
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class).all {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + listOf(
// Avoid having to stutter experimental annotations all over the codebase
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
"-opt-in=androidx.compose.runtime.ExperimentalComposeApi",
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
"-opt-in=com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi",
"-opt-in=com.google.accompanist.pager.ExperimentalPagerApi",
"-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi",
"-opt-in=kotlin.ExperimentalUnsignedTypes",
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-opt-in=kotlinx.coroutines.InternalCoroutinesApi"
)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With