Petite histoire de ce sujet: l'application met à jour les valeurs de la ligne cliquée avec la boîte de dialogue lorsqu'elle est confirmée. Utilise le scénario de pagination dans la base de données de la salle.
Lorsqu'un élément est ajouté ou supprimé, le dernier jeu de données est récupéré et transmis à la méthode submitList, puis toutes les modifications sont visibles et correctement traitées.
Le problème commence ici, si un élément existant est mis à jour, le dernier jeu de données est à nouveau récupéré correctement et transmis à submitList, mais cette fois, les modifications ne semblaient pas.
Lorsque je débogue le DIFF_CALLBACK
et attrape mon élément dans areItemsTheSame
, les valeurs newHistory
et oldHistory
sont identiques! (Comment!)
Il pourrait y avoir un bogue dans la méthode submitList
?
Après l’initialisation, observe
récupère la liste de la pièce et passe à mHistoryAdapter.submitList(it)
. Ensuite, si je mets à jour un élément, observe est à nouveau déclenché (et je vois la valeur mise à jour dans param it
) et passe à submitList
.
Malheureusement, l'adaptateur ne changera pas ...
mResolvedAddressViewModel = ViewModelProviders.of(this).get(ResolvedAddressViewModel::class.Java)
mResolvedAddressViewModel.getAddresses(false).observe(this, Observer {
mHistoryAdapter.submitList(it)
})
Toutes les parties
Modèle
@Parcelize
@Entity
data class ResolvedAddress(
@PrimaryKey var id: String = UUID.randomUUID().toString(),
var requestedLat: Double = 0.0,
var requestedLon: Double = 0.0,
var requestedAddress: String = "",
var lat: Double,
var lon: Double,
var address: String,
var country: String,
var countryCode: String,
var city: String,
var alias: String? = null,
var favorite: Boolean = false,
var provider: String? = null,
var lastUseDate: Long = 0L) : Parcelable
Adaptateur
class HistoryAdapter(var context: Context)
: PagedListAdapter<ResolvedAddress, HistoryItemHolder>(DIFF_CALLBACK) {
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<ResolvedAddress>() {
override fun areItemsTheSame(
oldHistory: ResolvedAddress, newHistory: ResolvedAddress): Boolean {
return oldHistory.id == newHistory.id
}
override fun areContentsTheSame(
oldHistory: ResolvedAddress, newHistory: ResolvedAddress): Boolean {
return oldHistory == newHistory
}
}
}
}
Fragment
class HistoryFragment : Fragment() {
private lateinit var mHistoryAdapter: HistoryAdapter
private lateinit var mResolvedAddressViewModel: ResolvedAddressViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_history, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerViewHistory.setHasFixedSize(true)
recyclerViewHistory.layoutManager = LinearLayoutManager(activity)
recyclerViewHistory.itemAnimator = DefaultItemAnimator()
mHistoryAdapter = HistoryAdapter(context!!)
recyclerViewHistory.adapter = mHistoryAdapter
mResolvedAddressViewModel = ViewModelProviders.of(this)
.get(ResolvedAddressViewModel::class.Java)
mResolvedAddressViewModel.getAddresses(false).observe(this, Observer {
mHistoryAdapter.submitList(it)
})
}
}
Il manque quelques éléments dans la question qui pourraient aider à fournir une réponse plus détaillée.
Ex. À quoi ressemble votre RecyclerView.Adapter
? Est-ce que cela étend PagedListAdapter
?
A quoi ressemble votre classe modèle? Est-ce une classe de données Kotlin?
Par souci de réponse, supposons que ces inconnues correspondent à nos attentes.
Si je comprends la question, il semble que vous êtes simplement updating
un élément et que vous ne supprimez ou n’ajoutez aucun élément . Par conséquent, le areItemsTheSame
de DiffUtil.ItemCallback
retournera toujours vrai, car l'ancienne liste et la nouvelle liste n'ont pas été modifiées Cela signifie que, si vous avez mis à jour un élément, vous avez probablement mis à jour son contenu et ne l'avez pas supprimé de la liste.
Par conséquent, areItemsTheSame
retournera la valeur true, car leurs identifiants sont toujours les mêmes.
Il est plus probable que la deuxième méthode, areContentsTheSame
, retourne false puisque vous avez mis à jour le contenu de l'élément.
Si votre classe de modèle, ResolvedAddress
, est une classe de données Kotlin, la méthode areContentsTheSame
doit renvoyer false lors de la comparaison de l'élément mis à jour à partir de l'ancienne et de la nouvelle liste. Cela devrait déclencher la méthode onBindViewHolder
dans votre adaptateur à ce stade pour vous permettre de relier cet élément aux données mises à jour.
Si ce modèle n'est pas un Kotlin data class
, vous devez vous assurer que la classe implémente la méthode compareTo
. Sinon, vous comparez l'adresse mémoire de l'objet avec le contenu réel de l'objet. Si tel est le cas, la méthode areContentsTheSame
retournera toujours la valeur true, l'adresse de mémoire de l'objet n'ayant pas changé.
Voici quelques conseils de débogage, car il est difficile de fournir une réponse plus claire sans plus de connaissances sur la manière dont le code a été implémenté.
J'avais un problème similaire, mais j'ai réussi à le résoudre en mettant à jour l'élément existant avec un nouvel objet plutôt qu'en mettant directement à jour l'élément existant, comme suggéré par cette réponse ici: