提问人:Bitwise DEVS 提问时间:11/25/2021 更新时间:11/25/2021 访问量:6142
ListAdapter submitList 未更新
ListAdapter submitList not updating
问:
我在 RecyclerView 中的分页无限滚动时遇到了这个问题,我正在使用.addAll()
movieList.addAll(it.movieList)
adapter.submitList(movieList)
Log.wtf("WTF", movieList.size.toString())
每当我们从 API 获得成功响应时,大小就会不断增加,这表明列表确实正在填充,但 RecyclerView 中的项目保持不变,并且似乎仅在第一次调用时起作用。submitList()
这是我的 DiffUtil 类和适配器
class DiffUtilMovies : DiffUtil.ItemCallback<MovieItem>() {
// DiffUtil uses this test to help discover if an item was added, removed, or moved.
override fun areItemsTheSame(oldItem: MovieItem, newItem: MovieItem): Boolean {
return oldItem.id == newItem.id
}
// Check whether oldItem and newItem contain the same data; that is, whether they are equal.
// If there are differences between oldItem and newItem, this code tells DiffUtil that the item has been updated.
override fun areContentsTheSame(oldItem: MovieItem, newItem: MovieItem): Boolean {
// Check for now if there is a difference on the price, removing specific fields
// means checking all the data for changes
return oldItem.title == newItem.title
}
}
class MovieAdapter(private val context: Context) : ListAdapter<MovieItem, MovieAdapter.ItemView>(DiffUtilMovies()) {
private var isDetached: Boolean = false
class ItemView(itemView: MovieCardBinding) : RecyclerView.ViewHolder(itemView.root) {
val titleTxt = itemView.titleTxt
val rateTxt = itemView.rateTxt
val rateBar = itemView.rateBar
val imageThumb = itemView.thumbnail
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemView {
return ItemView(
MovieCardBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: ItemView, position: Int) {
holder.apply {
val movieItem = getItem(position)
titleTxt.text = movieItem.title
rateTxt.text = movieItem.voteAverage.toString()
val rateAvg = movieItem.voteAverage?.toFloat() ?: run {
0.0f
}
rateBar.rating = rateAvg/2
if (!isDetached)
GlideApp.with(context)
.load(context.getString(R.string.image_link,AppConfig.image_endpoint, movieItem.posterPath))
.thumbnail(GlideApp.with(context).load(R.drawable.loading).centerCrop())
.error(R.drawable.no_image)
.into(imageThumb)
this.itemView.setOnClickListener {
try {
// context.startActivity(Intent(context, AssetInfoActivity::class.java).apply {
// putExtra(context.getString(R.string.assets), movieItem)
// })
}
catch (ignored: Exception){
// The user probably already leave before the activity started
}
}
}
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
super.onDetachedFromRecyclerView(recyclerView)
isDetached = true
}
}
答:
14赞
Tenfour04
11/25/2021
#1
ListAdapter 不适用于可变列表。这是因为,如果修改列表的内容,则当它尝试比较旧列表和新列表的内容时,它会将同一列表与自身进行比较。没有旧列表实例仍保留旧内容,因此它无法检测到任何差异。
例如,您应该创建一个新列表,而不是更改原始列表
movieList = movieList + it.movieList
adapter.submitList(movieList)
或者,您可以使用可变的后备列表,但在将副本传递给 时始终创建一个副本。即使在第一次通过 List 时,您也必须使用副本,这样它就不会引用您的可变列表。submitList
movieList.addAll(it.movieList)
adapter.submitList(movieList.toList())
评论
0赞
Bitwise DEVS
11/25/2021
是的,现在刚刚修好了。无论如何,谢谢,我仍然会标记这个答案
0赞
Bitwise DEVS
11/25/2021
但是,我仍然看到一些重复的项目,AFAIK DiffUtil 应该已经删除了重复的条目,对吗?
1赞
Bitwise DEVS
11/26/2021
哦,我以为它还包括避免重复的项目。谢谢你的信息。
1赞
Tenfour04
2/17/2022
DiffUtil 不负责对您的列表进行任何修改。由您来确保新列表按照您希望它们出现的顺序准确包含您想要的项目。DiffUtil 只负责弄清楚如何更改代表旧显示列表的视图持有者,以最有效的方式匹配您的新列表。当你打电话时,你是在说,“这个新列表正是我希望 ReyclerView 显示的内容。让它成为现实。submitList()
1赞
AJW
7/26/2023
@Tenfour04我做到了。明天晚上有时间的时候,我会发布一个新问题,展示所有的代码。
评论