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)
4 Réponses :
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
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) }
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é
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) }
Voilà la réponse. Merci beaucoup.
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 } }
@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,
Ê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, leToast
ne montrerait pas si la liste étaitnull
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 objetLiveData
incorrect (dans leViewModel
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