59
votes

comment obtenir viewModel par viewModels? (fragment-ktx)

Je travaille avec Single viewModel pour l'activité et tout son fragment.

Donc pour initialiser viewmodel si vous devez écrire ce code de configuration dans onActivityCreated de tous les fragments

    //ktx android
    implementation 'androidx.core:core-ktx:1.0.2'
    implementation 'androidx.fragment:fragment-ktx:1.0.0'
    implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"

J'étais en train de parcourir la page d'extension Android KTX: ( reportez-vous ici )

et j'ai trouvé que je pouvais initialiser le modèle de vue comme ceci:

    // Get a reference to the ViewModel scoped to this Fragment
    val viewModel by viewModels<MyViewModel>()

    // Get a reference to the ViewModel scoped to its Activity
    val viewModel by activityViewModels<MyViewModel>()

J'ai donc ajouté ci-dessous les dépendances à mon gradle (application):

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(activity!!).get(NoteViewModel::class.java)
    }

Mais lorsque j'essaie d'utiliser viewModels/activityViewModels dans mon application, leur référence n'est pas trouvée.

Je veux de l'aide sur la façon d'utiliser ces extensions avec un exemple de base que j'ai essayé de rechercher des exemples n'en ai trouvé aucun.


3 commentaires

Votre ViewModel prend-il un paramètre, comme le référentiel ou la base de données?


@IgorGanapolsky oui, je travaille avec une seule VM partagée entre tous les fragments.


Vous auriez besoin d'un ViewModelFactory alors


6 Réponses :


15
votes

essayer

implementation 'androidx.fragment:fragment-ktx:1.1.0-beta02'


10 commentaires

Je ne suis pas sûr de vouloir déplacer mon projet vers la version bêta.


by viewModels ne peut être appelé que dans Fragment, ou en activité également?


@IgorGanapolsky Ce délégué ne peut être appelé qu'à partir du Fragment. Mais si vous ajoutez l' implementation the "androidx.activity:activity-ktx:1.0.0" , vous pouvez utiliser un délégué similaire pour l'activité.


@Anmol La version dans la réponse est récemment passée à Stable. Vous devez être au moins sur 1.1.0 pour by ViewModels()


@MowDownJoe merci pour la mise à jour et maintenant le problème est résolu


@DenysMakhov Il n'y a pas de telle chose comme androidx.activity:activity-ktx


@IgorGanapolsky developer.android.com/jetpack/androidx/releases/activity


Je l'ai fait fonctionner lorsque j'ai utilisé activity-ktx 1.1.0 et étendu FragmentActivity () pas seulement Activity ()


@DenysMakhov Faux. fragment-ktx fonctionne à la fois pour l'activité et le fragment.


@ Dr.jacky Oui, peut-être que quelque chose a changé en un an.



3
votes

Vous utilisez cette dernière version alpha:

dependencies {
    implementation 'androidx.fragment:fragment-ktx:1.2.0-alpha01'
}


0 commentaires

2
votes

La fonction d'extension viewModels (...) a été ajoutée dans la version 1.1.0-alpha03 . Par conséquent, pour l'utiliser dans votre application, vous devrez implémenter le fragment-ktx des versions correspondant à 1.1.0-alpah03 ou version ultérieure.

Je viens de découvrir cela et j'ai donc eu recours à la version 1.1.0-rc01 parce que je ne voulais pas utiliser les versions alpha / bêta.


1 commentaires

impossible de l'utiliser avec 1.2.0-alpha02



67
votes

Enfin, nous avons une version stable.

Après être passé à l' implementation 'androidx.fragment:fragment-ktx:1.1.0' j'ai rencontré un autre problème.

Erreur du compilateur:

Impossible d'intégrer le bytecode créé avec la cible JVM 1.8 dans le bytecode en cours de création avec la cible JVM 1.6

build.gradle (Module: application)

compileOptions {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }

référence

Après avoir appliqué tout ce qui précède, le problème est résolu.

Merci tout le monde.


1 commentaires

Je travaille dans une application à plusieurs modules, y a-t-il un meilleur moyen de déclarer cette option de compilation dans chaque module.



-3
votes

Si vous êtes venu ici à la recherche d'une solution pour Koin :

Notez que vous pouvez utiliser Koin pour que cela fonctionne:

private val viewModel by viewModel<NoteViewModel>()

utiliserait l'importation

import org.koin.android.viewmodel.ext.android.viewModel

de la dépendance:

implementation "org.koin:koin-android-viewmodel:+" // changer + en w / e est le dernier lorsque vous lisez ceci


6 commentaires

(réponse car je me cherchais moi-même, et google m'a envoyé ici!)


oui, il est très difficile d'avoir les bonnes importations lors de l'utilisation de koin mais cette question n'est pas liée à koin.


La question s'est posée sur Google lors de la recherche de problèmes de Koin, (mêmes symptômes) donc on ne sait jamais :)


Pourquoi Koin est-il nécessaire?


Koin a la même API. Donc ce n'est pas nécessaire, c'est une alternative avec le même problème.


Je pense simplement que vous auriez mieux compris votre réponse si vous expliquez pourquoi vous suggérez des pièces de monnaie dans la réponse elle-même plutôt que des commentaires.



0
votes

Si vous ne souhaitez pas l'implémentation sur des bibliothèques, vous pouvez en fait définir une fonction vous-même

@MainThread
inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
        noinline factoryProducer: (() -> ViewModelProvider.Factory)? = null
): Lazy<VM> {
    val factoryPromise = factoryProducer ?: {
        val application = application ?: throw IllegalArgumentException(
                "ViewModel can be accessed only when Activity is attached"
        )
        ViewModelProvider.AndroidViewModelFactory.getInstance(application)
    }

    return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)
}


0 commentaires