我正在使用RecyclerViewwith ListAdapter(它使用AsyncListDiffer在列表被替换时计算和动画更改)。
问题是,如果我submit()列出了一些列表,然后重新排序该列表,submit()同样,什么也没有发生。
ListAdapter即使它“相同”(但顺序已更改),我如何强制评估此新列表?
新发现:
我检查了submitList() 的源代码,并在开始时进行了检查:
public void submitList(@Nullable final List<T> newList) {
final int runGeneration = ++this.mMaxScheduledGeneration;
if (newList != this.mList) {
Run Code Online (Sandbox Code Playgroud)
我认为这就是问题所在。但是如何度过呢?我的意思是,开发人员肯定考虑过提交不同的有序列表吗?
android android-recyclerview android-diffutils android-listadapter
背景
我有一个用户界面,显示用户全名列表,每个项目都有一个喜欢/不喜欢按钮。我正在使用一个ListAdapter底层用途DiffUtil和AsyncListDifferAPI。用户列表作为 LiveData 从 Room 数据库接收,并按"isLiked" 排序。
问题
每当点击“like”按钮时,Room(因为我正在使用 LiveData)会将新数据重新提交到适配器。问题是,由于列表按“isLiked”排序,喜欢的用户将更改其位置,并且 RecyclerView 将始终滚动到新位置。
我不想看到更新项目的新位置。那么,如何禁用自动滚动行为?
我尝试过的
MainActivity.kt
..
val userAdapter = UsersAdapter(this)
val ll = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recyclerView.apply {
layoutManager = ll
adapter = userAdapter
itemAnimator = null
setHasFixedSize(true)
}
viewModel.users.observe(this, {
// This will force the recycler view to scroll back to the previous position
// But it's more of a workaround than a clean solution.
val pos = ll.findFirstVisibleItemPosition()
userAdapter.submitList(it) { …Run Code Online (Sandbox Code Playgroud) android android-recyclerview android-paging android-diffutils android-listadapter
areItemsTheSame为什么需要与areContentsTheSameat diffutil recyclerview一起使用?我不明白我认为 areItemsTheSame 足以比较数据吗?可以给我更多解释吗?谢谢
在使用 ListAdapter 时,我注意到在更新项目后DiffUtil.ItemCallback areContentsTheSame()方法总是返回 true。调试代码我意识到旧的和新的项目完全一样(旧状态消失了)。因此,没有调用ListAdapter onBindViewHolder()方法来更新列表中的相应行(只有项目的顺序通过漂亮的动画更改)。
ListAdapter 不更新 reyclerview 中的项目
Recyclerview + Listadapter 中的项目不会在更新时重绘
带有 DiffUtil.ItemCallback 的 ListAdapter 始终认为对象相同
当向 RecyclerView ListAdapter 提交新列表时,差异检查始终为 areContentsTheSame() 返回 true
但是,上述答案(如果有)都没有提供正确的解决方案。
它对我有用的唯一方法是每次观察者发出新结果时在 ListAdapter 上调用notifyDataSetChanged()。
但是,如果通过强制 RecyclerView 重绘其内容(迄今为止显示的所有项目)而放弃了您可以获得的所有出色性能,那么使用 ListAdapter 和 submitList() 来通知更改的全部意义何在?
notifyDataSetChanged():即使它有效,如果您决定首先使用 ListAdapter,肯定不是正确的方法。
viewModel.getObjects().observe(this, listOfObjects -> listAdapter.submitList(new ArrayList<>(listOfObjects)));:没用。
更新列表中的项目后,我希望看到相应行的 UI(不仅是排序顺序)上发生的相应更改。
我在 RecyclerView 中遇到分页无限滚动的问题,我使用添加所有新项目.addAll()
movieList.addAll(it.movieList)
adapter.submitList(movieList)
Log.wtf("WTF", movieList.size.toString())
Run Code Online (Sandbox Code Playgroud)
每当我们从 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 …Run Code Online (Sandbox Code Playgroud) android kotlin android-recyclerview android-diffutils android-listadapter
我正在使用 DiffUtil.ItemCallback 和 ListAdapter 来更新 RecyclerView。
它工作得很好,但它的行为让我感到困扰。
根据文档,areContentsTheSame只有在areItemsTheSame返回时才应调用该方法true。
从文档:
仅当 areItemsTheSame(int, int) 为这些项目返回 true 时才调用此方法。
但是,就我而言,在使用新列表更新列表时,如下所示:
adapter.submitList(items.toMutableList())
Run Code Online (Sandbox Code Playgroud)
DiffUtil.ItemCallback 确实被触发,但即使areItemsTheSame返回true它也不会立即调用areContentTheSame(如预期的那样?),而是areItemsTheSame在不同的对象对上一次又一次地调用,(我在那里使用了带有断点的调试器)。经过areItemsTheSame几次调用并返回true,最后它会调用areContentTheSame,有时,我看到传递给的对象areContentTheSame实际上不一样!!并且有不同的id!!这意味着areContentTheSame甚至不应该调用这些对!
这是我的 DiffUtilCallback 的实现方式:
class AppDiffCallback : DiffUtil.ItemCallback<Item?>() {
override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
Timber.i("areItemsTheSame: called..")
if (oldItem.getItemType() == newItem.getItemType()) {
Timber.i("areItemsTheSame: done true..")
return true
}
Timber.w("areItemsTheSame: done false..")
return false
}
override fun areContentsTheSame(oldItem: Item, …Run Code Online (Sandbox Code Playgroud) android android-recyclerview android-diffutils android-listadapter
列表适配器 diffutil 未更新 recyclerview 中的列表项。
当我从列表中添加或删除项目时它会起作用。isSelected : Boolean = false但不会像对象类中那样更新任何特定值
当列表中的对象类之一发生更改(例如一个对象类中的布尔值更改)时,如何更新 recyclerview 视图
谢谢
下面的适配器类
class CategoryMainAdapter(
var itemClick : CategoryItemClick,
var screenWidth : Int = 0
) : ListAdapter<CategoryModel, CategoryMainAdapter.CategoryMainViewHolder>(CategoryMainDiffUtils()) {
inner class CategoryMainViewHolder(val binding : CategorySingleListLayoutBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryMainViewHolder {
val binding = CategorySingleListLayoutBinding.inflate(LayoutInflater.from
(parent.context),
parent,
false
)
return CategoryMainViewHolder(binding)
}
override fun onBindViewHolder(holder: CategoryMainViewHolder, position: Int) {
val model = getItem(position)
holder.apply {
binding.apply {
mainLinearLayout.layoutParams.apply {
width = …Run Code Online (Sandbox Code Playgroud) android listadapter kotlin android-recyclerview android-diffutils
我搜索项目,每次从服务器获取当我搜索“o”时它起作用,然后“ot”它再次起作用并且作为“o”搜索的结果我有20个项目,如果“ot”我有 10 个项目,它们是这 20 个项目的一部分,我确实删除了 EditText 中的 t,它显示了 20 个项目,只有 recyclerview 滚动指示器位于中间这是我的 diffUtil 代码
ListAdapter<Asset, SearchAdapter.ViewHolder>(object : DiffUtil.ItemCallback<Asset>() {
override fun areItemsTheSame(oldItem: Asset, newItem: Asset): Boolean {
return oldItem.assetId == newItem.assetId && oldItem.originalTitle ==newItem.originalTitle
}
override fun areContentsTheSame(oldItem: Asset, newItem: Asset): Boolean {
return oldItem == newItem
}
}
viewModel.searchAssets.observe(viewLifecycleOwner, Observer {
searchAdapter.submitList(it)
})
Run Code Online (Sandbox Code Playgroud)
在这里您可以看到我拍摄的视频 https://drive.google.com/drive/folders/1ia5y9TtL0PSAM1M4hVBILWcdSK1BDyKI?usp=sharing
当使用 DiffUtil ItemCallback 时,如何使用 DiffCallback 在 RecyclerView 中加载 newList。
当用户选择我希望 RecyclerView 更新的不同大小时,我想为用户提供从数据库返回不同大小列表的选项。
回收器视图适配器
RecyclerViewAdapter extends ListAdapter<WordEntity, RecyclerViewAdapter.ViewHolder> {
private RecyclerViewAdapter() {
super(DIFF_CALLBACK);
}
private static final DiffUtil.ItemCallback<WordEntity> DIFF_CALLBACK = new DiffUtil.ItemCallback<WordEntiti>() {
@Override
public boolean areItemsTheSame...
@Override
public boolean areContentsTheSame...
};
@Override
public viewHolder onCreateViewHolder...
@Override
public void onVindViewHolder ...
class ViewHolder extends RecyclerView.ViewHolder ...
public void updateWordList(List<WordEntity> words) {
final WordDiffCallBack diffCallBack = new WordDiffCallBack(list???, words);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallBack);
this.list???.clear();
this.addAll(words);
diffResult.dispatcheUpdatesTo(this);
}
Run Code Online (Sandbox Code Playgroud)
WordsDiffCallBack
private final List<WordEntity> …Run Code Online (Sandbox Code Playgroud) 更新:解决了一个问题:现在updateList解决了,问题是我定义mAdapter为RecyclerView.Adapter而不是MyAdapter。但是现在即使我正在获取数据,列表上也没有任何显示,它是空的
-------------------- 原始帖子 --------------------
我想更新我的RecyclerView用法DiffUtil以防止重复。
我有4个类:User类,Activity设置数据的Adapter类,类和DiffUtil类。我不确定我是否正确组合了所有这四个。
这是User类:
public class User {
private String mUserId;
private Uri mImageUrl;
public User(String userId, String imageUrl) {
mUserId = userId;
mImageUrl = Uri.parse(imageUrl);
}
public String getUserId() {
return mUserId;
}
public Uri getImageUrl() {
return mImageUrl;
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我动态设置数据的方式(我不断Json从服务器上获取要显示的包含用户ID的新数组,然后从Firebase存储中设置用户图像):(这是一个由onClick侦听器调用的函数:)
这是片段中的方法调用:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
updateUsersList();
} …Run Code Online (Sandbox Code Playgroud) java android recycler-adapter android-recyclerview android-diffutils