1
votes

MutableLiveData ArrayList est vide même après postValue () Kotlin

Je suis maintenant bloqué et je me demande actuellement pourquoi mon arraylist mutable renvoie null même s'il est mis à jour avec postvalue (). J'ai essayé de l'afficher en utilisant Toast et il a affiché [] qui je pense est nul. Il n'y avait pas d'espace entre les deux, donc cela ressemblait à une boîte. J'ai également fait toString () pour afficher le texte. Comment pourrais-je résoudre ce problème?

Voici mon activité principale:

private fun observeInput(viewmodel: viewmodel) {
    viewmodel.Testlist.observe(viewLifecycleOwner, Observer {
        it?.let {
            Toast.makeText(context, it.toString(), Toast.LENGTH_LONG).show()
        }
    })
}

ViewModel:

activity?.let {
    val viewmodel = ViewModelProviders.of(this).get(viewmodel::class.java)
    observeInput(viewmodel)
}

Fragment:

Zone supérieure:

class viewmodel: ViewModel() {
    val Testlist: MutableLiveData<ArrayList<String>> = MutableLiveData()
    init {
        Testlist.value = arrayListOf()
    }
}

Zone inférieure:

val list = ArrayList<String>()
list.add("text1")
list.add("text2")
val viewmodel = ViewModelProviders.of(this).get(viewmodel::class.java)
viewmodel.Testlist.postValue(list)


8 commentaires

Êtes-vous sûr que postValue est exécuté une fois que l'observation est définie dans le fragment? Sinon, vous recevrez une liste vide de résultat de l'initialisation dans ViewModel.


@NelsonAlmendra Oui, c'est vrai. Je l'ai essayé.


êtes-vous sûr d'utiliser postvalue () dans le bon fil de discussion?


@TechMaxed essaie d'utiliser viewmodel.Testlist.value = list pour voir si cela fait une différence.


La façon dont vous obtenez le ViewModel dans le fragment est omise, de sorte que cette question ne peut pas être répondue avec certitude.


La liste n'est pas null , elle est vide. Les crochets vides sont ce que vous obtenez lorsque vous imprimez une liste vide. De plus, le Toast ne montrerait pas si la liste était null car l'appel approprié est exécuté dans le bloc ? .Let {} . Il semble que vous définissiez l'observateur après avoir publié la valeur ou que vous publiez la valeur dans un objet LiveData incorrect (dans le ViewModel de l'activité qui n'est pas partagé avec le fragment par exemple ).


@NelsonAlmendra J'ai essayé d'utiliser la .value mais cela ne fonctionnait toujours pas :(


@EpicPandaForce Désolé, mais je ne comprends pas ce que vous voulez dire. Pouvez-vous expliquer ce que vous vouliez dire? Merci


4 Réponses :


1
votes

avez-vous utilisé la même instance de votre modèle de vue? ou avez-vous défini un autre modèle de vue dans la classe de fragment? Le problème peut être que vous accédez à une instance différente du modèle de vue et non à celle où le MutableLiveData a été mis à jour


0 commentaires

1
votes

Vous pouvez utiliser ceci:

class UAppCompatActivity : AppCompatActivity() {

    protected fun <T : Any?> MutableLiveData<ArrayList<T>>.default(initialValue: ArrayList<T>) = apply { setValue(initialValue) }

    protected fun <T> MutableLiveData<ArrayList<T>>.addItem(item: T) {
        val updatedItems = this.value as ArrayList
        updatedItems.add(item)
        this.value = updatedItems
    }

    protected fun <T> MutableLiveData<ArrayList<T>>.deleteItem(item: T) {
        val updatedItems = this.value as ArrayList
        updatedItems.remove(item)
        this.value = updatedItems
    }

    ...

puis utiliser cette fonction comme ci-dessous:

    viewmodel.Testlist.default(ArrayList())

Pour moi, j'ai une BaseActivity qui d'autres activités en découlent:

    fun <T : Any?> MutableLiveData<ArrayList<T>>.default(initialValue: ArrayList<T>) = apply { setValue(initialValue) }


6 commentaires

Où dois-je le mettre? Merci


Vous pouvez mettre votre BaseActivity pour l'utiliser à partir de chaque activité, mais dans votre cas, il peut être bon de le mettre dans MainActivity et au lieu de postValue, utilisez la méthode par défaut.


@ z95510 J'ai mis le plaisir à la fin de l'activité principale et j'ai utilisé le viewmodel.Testlist ... en haut. Cela n'a toujours pas résolu le problème :(


Regarde à nouveau ma réponse, j'ai ajouté plus de détails pour toi


en fait, vous ne devriez pas utiliser viewmodel.Testlist.default (ArrayList ()), vous devez publier votre liste à la place de viewmodel.Testlist.default (list)


Je viens de l'essayer et cela ne fonctionne toujours pas. Souhaitez-vous le supprimer ou le conserver ici? Merci de m'avoir aidé



3
votes

Vous publiez la valeur dans l'objet LiveData dans le viewmodel de l'activité, qui n'est pas la même instance que le viewmodel du fragment. Examinons la façon dont vous instanciez le viewmodel dans votre fragment:

activity?.let { val viewmodel = ViewModelProviders.of(it).get(viewmodel::class.java) }

Pour obtenir un viewmodel qui est partagé entre votre activité et fragment, vous devez transmettre l'activité en tant que propriétaire:

activity?.let {
    // activity can be refered by the implicit parameter `it`
    // `this` refers to the current fragment hence it's the owner of the view model
    val viewmodel = ViewModelProviders.of(this).get(viewmodel::class.java)
    observeInput(viewmodel)
}


1 commentaires

Voilà la réponse. Merci beaucoup.



1
votes

Vous pouvez probablement consulter un exemple du guide du développeur pour résoudre votre problème

https://developer.android.com/topic/libraries/architecture/viewmodel.html#kotlin

// modèle de vue partagé

model = activity?.run {
        ViewModelProviders.of(this)[SharedViewModel::class.java]
} ?: throw Exception("Invalid Activity")

model.getUsers().observe(this, Observer<List<User>>{ users ->
      // update UI
})

// Joindre ViewModel In Activity onCreate ()

val model = ViewModelProviders.of(this)[SharedViewModel::class.java]

val list = arrayListOf<String>()
list.add("user1")
list.add("user2")

model.setUsers(list)

// Obtenir la même instance ViewModel In fragment onCreateView ()

 class SharedViewModel : ViewModel() {
    private val usersList: MutableLiveData<List<String>>()

    fun getUsers(): LiveData<List<String>> {
        return usersList
    }

    fun setUsers(users: List<String>) {
        usersList.value = users
    }
 }


2 commentaires

@TechMaxed voir ma réponse mise à jour si cela peut vous aider


Merci d'avoir essayé de m'aider mais j'ai déjà trouvé une réponse ci-dessus. Votre réponse est toujours une bonne réponse, je l'ai donc votée,