web-dev-qa-db-fra.com

Thilt ViewModel et composer ne fonctionne pas ensemble

Cela ressemble à l'officiel Android Docs La manière d'utiliser une injection de compose, de la poignée et de la vision avec la navigation ne fonctionne pas.

J'ai la configuration suivante:

Un écran principal, qui héberge uniquement le contrôleur NAV. L'écran d'accueil indique un bouton pour. Navigation sur l'écran de nom qui a un modèle de vue.

@Composable
fun MainScreen() {
    val navController = rememberNavController()
    NavHost(navController, startDestination = "home") {
        composable("home") {
            HomeScreen() {
                navController.navigate("my/Name")
            }
        }

        composable("my/{name}") { navBackStackEntry ->
            val viewModel: NameScreenViewModel = hiltViewModel(navBackStackEntry)
            NameScreen(viewModel)
        }
    }
}
@Composable
fun HomeScreen(onButtonClicked: () -> Unit) {
    Button(onClick = onButtonClicked, modifier = Modifier.padding(8.dp)) {
        Text("Continue")
    }
}
@HiltViewModel
class NameScreenViewModel @Inject constructor(private val test: TestClass): ViewModel() {
    var name = MutableLiveData("empty")

    fun change() {
        name.value = test.load()
    }
}

@Composable
fun NameScreen(viewModel: NameScreenViewModel) {
    val name by viewModel.name.observeAsState()

    Column {
        Text("Hi there, $name")

        Button(onClick = { viewModel.change() }) {
            Text("Click me!")
        }
    }
}

L'activité et l'application ont les annotations correctes:

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeViewModelTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    MainScreen()
                }
            }
        }
    }
}
@HiltAndroidApp
class MainApplication : Application() {
}

La classe injectée est très simple et est même enregistrée pour être fournie au lieu d'utiliser l'annotation du constructeur:

class TestClass {
    fun load(): String {
        return "name"
    }
}
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
    @Provides
    @Singleton
    fun providesTestClass(): TestClass {
        return TestClass()
    }
}

Si vous utilisez hiltViewModel comme ci-dessus, l'application s'écrasera avec l'erreur

Java.lang.IllegalStateException: Given component holder class eu.meecolabs.composeviewmodel.MainActivity does not implement interface dagger.hilt.internal.GeneratedComponent or interface dagger.hilt.internal.GeneratedComponentManager
        at dagger.hilt.EntryPoints.get(EntryPoints.Java:62)
        at dagger.hilt.Android.internal.lifecycle.HiltViewModelFactory.createInternal(HiltViewModelFactory.Java:129)
        at androidx.hilt.navigation.HiltViewModelFactory.create(HiltNavBackStackEntry.kt:56)
        at eu.meecolabs.composeviewmodel.ui.ComposableSingletons$MainScreenKt$lambda-1$1.invoke(MainScreen.kt:26)
        at eu.meecolabs.composeviewmodel.ui.ComposableSingletons$MainScreenKt$lambda-1$1.invoke(MainScreen.kt:25)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.navigation.compose.NavHostKt$NavHost$6$1.invoke(NavHost.kt:146)
        at androidx.navigation.compose.NavHostKt$NavHost$6$1.invoke(NavHost.kt:145)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
        at androidx.compose.runtime.saveable.SaveableStateHolderImpl.SaveableStateProvider(SaveableStateHolder.kt:84)
        at androidx.navigation.compose.NavBackStackEntryProviderKt.SaveableStateProvider(NavBackStackEntryProvider.kt:59)
        at androidx.navigation.compose.NavBackStackEntryProviderKt.access$SaveableStateProvider(NavBackStackEntryProvider.kt:1)
        at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:51)
        at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:50)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
        at androidx.navigation.compose.NavBackStackEntryProviderKt.LocalOwnersProvider(NavBackStackEntryProvider.kt:46)
        at androidx.navigation.compose.NavHostKt$NavHost$6.invoke(NavHost.kt:145)
        at androidx.navigation.compose.NavHostKt$NavHost$6.invoke(NavHost.kt:144)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.animation.CrossfadeKt$Crossfade$1$1.invoke(Crossfade.kt:74)
        at androidx.compose.animation.CrossfadeKt$Crossfade$1$1.invoke(Crossfade.kt:69)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
        at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:86)
        at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:144)
        at androidx.navigation.compose.NavHostKt$NavHost$7.invoke(Unknown Source:13)
        at androidx.navigation.compose.NavHostKt$NavHost$7.invoke(Unknown Source:10)
        at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2156)
        at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2399)
        at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2580)
        at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2573)
        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(SnapshotState.kt:540)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2566)
2021-07-27 17:46:40.678 22501-22501/? E/AndroidRuntime:     at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:2542)
        at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:613)
        at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:764)
        at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:103)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:447)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:416)
        at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.Android.kt:34)
        at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.Android.kt:109)
        at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.Android.kt:41)
        at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.Android.kt:69)
        at Android.view.Choreographer$CallbackRecord.run(Choreographer.Java:965)
        at Android.view.Choreographer.doCallbacks(Choreographer.Java:791)
        at Android.view.Choreographer.doFrame(Choreographer.Java:722)
        at Android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.Java:952)
        at Android.os.Handler.handleCallback(Handler.Java:883)
        at Android.os.Handler.dispatchMessage(Handler.Java:100)
        at Android.os.Looper.loop(Looper.Java:214)
        at Android.app.ActivityThread.main(ActivityThread.Java:7356)
        at Java.lang.reflect.Method.invoke(Native Method)
        at com.Android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.Java:491)
        at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:940)

J'utilise le dernier Android Studio Aperçu et les versions de dépendance suivantes:

ext {
        compose_version = '1.0.0-rc02'
        hilt_version = '2.38'
    }
    dependencies {
        classpath "com.Android.tools.build:gradle:7.1.0-alpha04"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10"

        classpath "com.google.dagger:hilt-Android-gradle-plugin:$hilt_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
implementation 'androidx.core:core-ktx:1.6.0'

    implementation 'androidx.appcompat:appcompat:1.3.1'

    implementation 'com.google.Android.material:material:1.4.0'

    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"

    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'

    implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'

    implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07'

    implementation 'androidx.activity:activity-compose:1.3.0-rc02'

    implementation "androidx.navigation:navigation-compose:2.4.0-alpha05"
    implementation 'androidx.hilt:hilt-navigation-compose:1.0.0-alpha03'

    implementation "com.google.dagger:hilt-Android:$hilt_version"
    kapt "com.google.dagger:hilt-compiler:$hilt_version"
    kapt 'androidx.hilt:hilt-compiler:1.0.0'

Je ne sais vraiment pas quoi essayer d'autre. J'ai déjà vérifié tant de combinaisons différentes et lisez-la à travers les poteaux complets ou blogs à la main ou SO problèmes, mais tous semblent utiliser des bibliothèques obsolètes ou il ne semble pas y avoir une solution réelle.

4
dst

J'ai résolu ceci en utilisant ci-dessous

class MyScreenManager(navController:NavigationController){

lateinit var viewModel:MyViewModel = HiltViewModelFactory(
            activity,
            navController.getBackStackEntry(MyScreen.route)
        ).create(MyViewModel::class.Java)
}

L'hébergement de classe ce code n'a pas été injecté mais navigué à.

0
D Lad