How to overcome / solve the next snippet to fulfill Jetpack Compose compiler (synthetic sample):
enum class UINavigator: @Composable () -> Unit {
MAIN;
private val nav: NavHostController = rememberNavController()
override operator fun invoke() = ...
}
Error:
@Composable invocations can only happen from the context of a @Composable function
However, UINavigator
already implements Higher Order Function.
Is it a bug or a restriction which doesn't cover in Documentation ?
CodePudding user response:
This error likely comes from two parts.
A) nav
is defined as a property inside the class. This is instantiated when the class is created, which is not necessarily in a Composable Scope. Additionally, this is an enum class which means that it's instantiated statically (depending on the VM, could happen at launch or when first read).
B) The Compose compiler plugin adds some magic to functions so even if we add the @Composable annotation to the overridden function, there is a conflict introduced:
There are a couple of things you can try:
Option A: Define an operator without extending a function type:
enum class UINavigator {
MAIN;
@Composable operator fun invoke() {
val nav: NavHostController = rememberNavController()
// ...
}
}
You can still use it as a function. Note that the nav
property. If you want to share state across them all, you can either use a StateFlow
or a Composition Local.
Option B: Using extension functions
enum class UINavigator {
MAIN;
}
@Composable operator fun UINavigator.invoke() {
val nav: NavHostController = rememberNavController()
// ...
}
To all effects, the same as option A.