Vee*_*ath 46 android listadapter kotlin
我正在使用新的支持库ListAdapter
.这是我的适配器代码
class ArtistsAdapter : ListAdapter<Artist, ArtistsAdapter.ViewHolder>(ArtistsDiff()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(parent.inflate(R.layout.item_artist))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position))
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(artist: Artist) {
itemView.artistDetails.text = artist.artistAlbums
.plus(" Albums")
.plus(" \u2022 ")
.plus(artist.artistTracks)
.plus(" Tracks")
itemView.artistName.text = artist.artistCover
itemView.artistCoverImage.loadURL(artist.artistCover)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我正在更新适配器
musicViewModel.getAllArtists().observe(this, Observer {
it?.let {
artistAdapter.submitList(it)
}
})
Run Code Online (Sandbox Code Playgroud)
我的差异类
class ArtistsDiff : DiffUtil.ItemCallback<Artist>() {
override fun areItemsTheSame(oldItem: Artist?, newItem: Artist?): Boolean {
return oldItem?.artistId == newItem?.artistId
}
override fun areContentsTheSame(oldItem: Artist?, newItem: Artist?): Boolean {
return oldItem == newItem
}
}
Run Code Online (Sandbox Code Playgroud)
发生的事情是在适配器第一次呈现所有项目时调用submitList,但是当使用更新的对象属性再次调用submitList时,它不会重新呈现已更改的视图.
当我滚动列表时,它会重新呈现视图,而列表又会调用 bindView()
此外,我注意到adapter.notifyDatasSetChanged()
提交列表后调用呈现更新值的视图,但我不想调用,notifyDataSetChanged()
因为列表适配器内置了diff utils
有人能帮我一下吗?
ins*_*a_c 58
编辑:我理解为什么会发生这不是我的观点.我的观点是,它至少需要发出警告或调用该notifyDataSetChanged()
函数.因为显然我正在调用这个submitList(...)
函数是有原因的.我很确定人们会在几个小时之前弄清楚出了什么问题,直到他们发现submitList()无声地忽略了这个调用.
这是因为Google
奇怪的逻辑.因此,如果您将相同的列表传递给适配器,它甚至不会调用DiffUtil
.
public void submitList(final List<T> newList) {
if (newList == mList) {
// nothing to do
return;
}
....
}
Run Code Online (Sandbox Code Playgroud)
ListAdapter
如果无法处理同一列表中的更改,我真的不明白这一点.如果您想要更改列表中的项目并转到ListAdapter
并查看更改,则需要创建列表的深层副本,或者需要定期RecyclerView
使用自己的DiffUtill
类.
Min*_*mir 29
使用 Kotlin,您只需根据您的使用情况将列表转换为新的MutableList像这样或其他类型的列表
.observe(this, Observer {
adapter.submitList(it?.toMutableList())
})
Run Code Online (Sandbox Code Playgroud)
RJF*_*res 27
该库假设您正在使用Room或任何其他ORM,每次更新时都会提供一个新的异步列表,因此只需在其上调用submitList即可,对于草率开发人员,如果调用相同的列表,则会阻止执行两次计算.
接受的答案是正确的,它提供了解释,但没有提供解决方案.
如果您没有使用任何此类库,您可以做的是:
submitList(null);
submitList(myList);
Run Code Online (Sandbox Code Playgroud)
另一个解决方案是覆盖submitList(不会导致快速闪烁):
@Override
public void submitList(final List<Author> list) {
super.submitList(list != null ? new ArrayList<>(list) : null);
}
Run Code Online (Sandbox Code Playgroud)
有点迟钝的逻辑,但工作完美.我首选的方法是第二个方法,因为它不会导致每一行获得onBind调用.
Jan*_*elý 20
我也有类似的问题,但不正确的渲染是由共同造成setHasFixedSize(true)
和android:layout_height="wrap_content"
。第一次,适配器提供了一个空列表,因此高度从未更新,并且是0
. 无论如何,这解决了我的问题。其他人可能有同样的问题,并会认为这是适配器的问题。
Yoa*_*n.G 11
如果您在使用过程中遇到一些问题
recycler_view.setHasFixedSize(true)
你应该绝对检查这个评论:https : //github.com/thoughtbot/expandable-recycler-view/issues/53#issuecomment-362991531
它解决了我这边的问题。
(这是应要求的评论截图)
今天我也偶然发现了这个“问题”。在insa_c 的回答和RJFares 的解决方案的帮助下,我为自己做了一个 Kotlin 扩展函数:
/**
* Update the [RecyclerView]'s [ListAdapter] with the provided list of items.
*
* Originally, [ListAdapter] will not update the view if the provided list is the same as
* currently loaded one. This is by design as otherwise the provided DiffUtil.ItemCallback<T>
* could never work - the [ListAdapter] must have the previous list if items to compare new
* ones to using provided diff callback.
* However, it's very convenient to call [ListAdapter.submitList] with the same list and expect
* the view to be updated. This extension function handles this case by making a copy of the
* list if the provided list is the same instance as currently loaded one.
*
* For more info see 'RJFares' and 'insa_c' answers on
* /sf/ask/3480846981/
*/
fun <T, VH : RecyclerView.ViewHolder> ListAdapter<T, VH>.updateList(list: List<T>?) {
// ListAdapter<>.submitList() contains (stripped):
// if (newList == mList) {
// // nothing to do
// return;
// }
this.submitList(if (list == this.currentList) list.toList() else list)
}
Run Code Online (Sandbox Code Playgroud)
然后可以在任何地方使用,例如:
viewModel.foundDevices.observe(this, Observer {
binding.recyclerViewDevices.adapter.updateList(it)
})
Run Code Online (Sandbox Code Playgroud)
并且它只(并且总是)复制与当前加载的列表相同的列表。
小智 6
在同一个案例中浪费了很多时间来找出问题。
但在我的情况下,问题是我忘记为我的 recyclerView 指定一个 layoutManager: vRecyclerView.layoutManager = LinearLayoutManager(requireContext())
希望没有人重蹈我的覆辙……
我有一些奇怪的行为。我在 LiveDate 中使用 MutableList。
在 kotlin 中,以下代码不起作用:
mViewModel.products.observe(viewLifecycleOwner, {
mAdapter.submitList(it)
})
Run Code Online (Sandbox Code Playgroud)
但是,当我将其更改为 it.toList() 时,它起作用了
mViewModel.products.observe(viewLifecycleOwner, {
mAdapter.submitList(it.toList())
})
Run Code Online (Sandbox Code Playgroud)
虽然,“它”是同一个列表。
归档时间: |
|
查看次数: |
9914 次 |
最近记录: |