标签: android-diffutils

如果我以不同的项目顺序提交相同的列表,则 ListAdapter 不会刷新 RecyclerView

我正在使用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

14
推荐指数
1
解决办法
9243
查看次数

如何禁用更新项目时发生的 RecyclerView (ListAdapter) 自动滚动?

背景

我有一个用户界面,显示用户全名列表,每个项目都有一个喜欢/不喜欢按钮。我正在使用一个ListAdapter底层用途DiffUtilAsyncListDifferAPI。用户列表作为 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

11
推荐指数
0
解决办法
1461
查看次数

为什么在 diffutil recyclerview 中使用 areItemsTheSame 和 areContentsTheSame?

areItemsTheSame为什么需要与areContentsTheSameat diffutil recyclerview一起使用?我不明白我认为 areItemsTheSame 足以比较数据吗?可以给我更多解释吗?谢谢

android compare list android-recyclerview android-diffutils

11
推荐指数
1
解决办法
5004
查看次数

DiffUtil ItemCallback areContentsTheSame() 在更新 ListAdapter 上的项目后始终返回 true

在使用 ListAdapter 时,我注意到在更新项目后DiffUtil.ItemCallback areContentsTheSame()方法总是返回 true。调试代码我意识到旧的和新的项目完全一样(旧状态消失了)。因此,没有调用ListAdapter onBindViewHolder()方法来更新列表中的相应行(只有项目的顺序通过漂亮的动画更改)。

检查 Stackoverflow 上的其他问题似乎是许多开发人员面临的常见问题:

ListAdapter 不更新 reyclerview 中的项目

编辑内容时 ListAdapter 未更新

DiffUtil.Callback 未按预期工作

Recyclerview + Listadapter 中的项目不会在更新时重绘

带有 DiffUtil.ItemCallback 的 ListAdapter 始终认为对象相同

当向 RecyclerView ListAdapter 提交新列表时,差异检查始终为 areContentsTheSame() 返回 true

但是,上述答案(如果有)都没有提供正确的解决方案。

它对我有用的唯一方法是每次观察者发出新结果时在 ListAdapter 上调用notifyDataSetChanged()

但是,如果通过强制 RecyclerView 重绘其内容(迄今为止显示的所有项目)而放弃了您可以获得的所有出色性能,那么使用 ListAdapter 和 submitList() 来通知更改的全部意义何在?

  1. notifyDataSetChanged()

即使它有效,如果您决定首先使用 ListAdapter,肯定不是正确的方法。

  1. viewModel.getObjects().observe(this, listOfObjects -> listAdapter.submitList(new ArrayList<>(listOfObjects)));

没用。

更新列表中的项目后,我希望看到相应行的 UI(不仅是排序顺序)上发生的相应更改。

android listadapter android-recyclerview android-diffutils

10
推荐指数
2
解决办法
2547
查看次数

ListAdapter 提交列表未更新

我在 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

9
推荐指数
1
解决办法
6594
查看次数

DiffUtil.Callback 未按预期工作

我正在使用 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

8
推荐指数
0
解决办法
2234
查看次数

列表适配器 Diff Util 不更新 Recyclerview 中的列表项

列表适配器 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

8
推荐指数
1
解决办法
6464
查看次数

将 Recyclerview 与 DiffUtil.ItemCallback 一起使用不会滚动到顶部?

我搜索项目,每次从服务器获取当我搜索“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

android android-recyclerview android-diffutils

7
推荐指数
2
解决办法
2456
查看次数

如何使用 DiffUtils 更新 RecyclerView 中的列表?

当使用 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)

android android-recyclerview android-diffutils

7
推荐指数
2
解决办法
6434
查看次数

我的DiffUtil实现有什么问题?

更新:解决了一个问题:现在updateList解决了,问题是我定义mAdapterRecyclerView.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

6
推荐指数
1
解决办法
2021
查看次数