标签: android-diffutils

我的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
查看次数

RecycleViewAdapter 中的 List 内容更新后,DiffUtil areContentsTheSame() 始终返回 true

这是我的 RecyclerView 适配器类。单击列表 UI 中的某个项目应将特定项目(如背景黑色变为白色)更改。单击某个项目后,我将 UI 类中的项目状态从 0 更改为 1,根据该状态 UI 应该更改该项目。但在 diffUtil areContentTheSame() 内部返回 true。

class TimeSlotsAdapter(val adapterItemOnClick: (TimeSlots) -> Unit):RecyclerView.Adapter<TimeSlotsAdapter.TimeSlotsViewHolder>() {

private lateinit var binding: RvTimeSlotsBinding
private var timeSlots: List<TimeSlots> = ArrayList<TimeSlots>()


inner class TimeSlotsViewHolder : RecyclerView.ViewHolder {
    constructor(rvBinding: RvTimeSlotsBinding) : super(rvBinding.root) {
    }

    fun setItem(timeSlots: TimeSlots) {
        binding.timeSlotView.setOnClickListener { adapterItemOnClick(timeSlots) }
    }
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimeSlotsViewHolder {
    binding =
        RvTimeSlotsBinding.inflate(LayoutInflater.from(parent.context), parent, false)
    return TimeSlotsViewHolder(binding)
}

override fun onBindViewHolder(holder: TimeSlotsViewHolder, position: Int) {
    timeSlots[position]?.let …
Run Code Online (Sandbox Code Playgroud)

android-recyclerview android-diffutils

6
推荐指数
0
解决办法
333
查看次数

使用 diff utils 更新回收器视图适配器,添加项目时无法正常工作

我正在使用 diff utils 来更新我的回收器视图(来自视图模型的实时数据返回一个列表),我有一个项目装饰,它向列表中的最后一个元素添加了大量填充,但 diff utils 正确更新了回收器视图通过调用notifyItemInserted而不是notifyDataSetChanged,装饰仅应用于添加的最后一个元素,因此如果我将一个项目添加到我的回收器视图并调用notify dataset更改了适配器重建,那么我的所有项目最终都会有大量填充所有项目和填充仅在最后一个元素上(这是我想要的),如果我添加相同的项目两次,它会在最后添加之前添加它,例如,如果我有一个 1,2,3 的列表并且我添加在现有 3 之前添加了另外 3 个,所以 1,2,3b,3a,有没有办法对此进行更多控制?

物品装饰

public class PredictionsHorizontalSpaceCardDecoration extends RecyclerView.ItemDecoration {

private final int horizontalSpace;
private final int endSpace;

public PredictionsHorizontalSpaceCardDecoration(int horizontalSpace, int endSpace) {
    this.horizontalSpace = horizontalSpace;
    this.endSpace = endSpace;
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    Log.d("Deco", "parent child count " + (parent.getChildCount() - 1) + " position " + parent.getChildAdapterPosition(view));
    outRect.right = horizontalSpace;
    outRect.top = horizontalSpace;
    outRect.bottom = horizontalSpace;
    outRect.left …
Run Code Online (Sandbox Code Playgroud)

android android-recyclerview item-decoration android-diffutils

5
推荐指数
1
解决办法
495
查看次数

如何修复使用 DiffUtil 向 ListUpdateCallback 发送更新时得到的错误位置

我有一个 Android 应用程序,用户可以在其中同时修改多个String项目EditText,所以我需要弄清楚发生了什么变化,以便将更改通知服务器(创建新项目、更新现有项目或删除后者),这就是为什么我使用DiffUtilwithListUpdateCallback来做到这一点。如果旧列表的大小为 2 项的问题;并且我删除了索引 0 处的项目,然后在列表末尾添加了 3 个项目,我得到了一个onInserted带有不正确位置参数的回调,导致IndexOutOfBoundsException, (这是删除旧列表中任何项目的行为,除了最后一个)请看一下这个显示问题的 GIF

我已经尝试了以下代码,并对新列表进行了其他更改,例如在索引 1 处删除,然后在列表末尾添加 3 个项目,它工作正常!

我正在使用的数组是 Answer 类型,它是一个类:

public class Answer {
    private String id;
    private String questionId;
    private String text;
    private Integer count;
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果两个项目相同,则可以通过 id 标识 2 个不同的对象;然后可以通过文本识别内容。

DiffUtil.Callback

public class AnswersDiffCallback extends DiffUtil.Callback {

    List<Answer> newAnswers;
    List<Answer> oldAnswers;

    public AnswersDiffCallback(List<Answer> newAnswers, List<Answer> oldAnswers) {
        this.newAnswers = newAnswers;
        this.oldAnswers = oldAnswers;
    } …
Run Code Online (Sandbox Code Playgroud)

java android android-diffutils

5
推荐指数
1
解决办法
634
查看次数

如何将 DiffUtil 与多种视图类型一起使用

我已经实现了具有多种视图类型的 recyclerview ,并且我想添加 DiffUtil 。我设法为一种类型做到这一点,但是当我尝试支持多种视图类型时,我不能

所以我的问题是:DiffUtil 是否支持多种视图类型,是否有一个很好的 java 实现教程

我的适配器


public class PostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {


    private final int VIEW_TYPE_ITEM = 0;
    private final int VIEW_TYPE_AD = 1;
    private final int VIEW_TYPE_CATEGORIES = 2;
    private final int VIEW_TYPE_NULL = 99;

    private Context context;
    private List<Object> postList;

    public PostsAdapter() {
    }

    /*public PostsAdapter() {
        super(Post.DIFF_CALLBACK);
    }*/

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        context = parent.getContext();

        switch (viewType){
            case VIEW_TYPE_ITEM:
                View viewItem = LayoutInflater.from(context).inflate(R.layout.item_post,
                        parent, false);
                return new …
Run Code Online (Sandbox Code Playgroud)

android android-studio android-recyclerview android-diffutils

5
推荐指数
1
解决办法
3235
查看次数

协程、异步 DiffUtil 和不一致检测错误

我在将 Kotlin Flows 和 async DiffUtil 放在一起时遇到了麻烦。

我的 RecyclerView.Adapter 中有这个函数,它在计算线程上计算一个 DiffUtil 并将更新分派到主线程上的 RecyclerView :

suspend fun updateDataset(newDataset: List<Item>) = withContext(Dispatchers.Default) {
        val diff = DiffUtil.calculateDiff(object : DiffUtil.Callback()
        {
            override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean
                    = dataset[oldItemPosition].conversation.id == newDataset[newItemPosition].conversation.id

            override fun getOldListSize(): Int = dataset.size
            override fun getNewListSize(): Int = newDataset.size

            override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean
                    = dataset[oldItemPosition] == newDataset[newItemPosition]
        })

        withContext(Dispatchers.Main) {
            dataset = newDataset // <-- dataset is the Adapter's dataset
            diff.dispatchUpdatesTo(this@ConversationsAdapter)
        }
    }
Run Code Online (Sandbox Code Playgroud)

我从我的 Fragment …

android kotlin android-recyclerview kotlin-coroutines android-diffutils

4
推荐指数
1
解决办法
1216
查看次数

AsyncListDiffer 没有更新 recyclerview

我有一个 RecyclerView 和一个使用AssyncListDiffer的适配器。我遇到的问题是,当 LiveData 发生更改时,recyclerview不会更新。观察者会收到通知,但列表不会更新。

这是我的适配器:

class HourAdapter(private val interaction: HourInteraction? = null) :
RecyclerView.Adapter<HourAdapter.HourViewHolder>() {

    private val differ = AsyncListDiffer(this, DIFF_CALLBACK)

    fun submitList(list: List<Hour>?) {
        differ.submitList(list)
    }

    private fun getHourAt(position: Int): Hour {
        return differ.currentList[position]
    }

    override fun getItemCount(): Int {
        return differ.currentList.size
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HourViewHolder {...}

    override fun onBindViewHolder(holder: HourViewHolder, position: Int) {...}

    val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Hour>() {

      override fun areItemsTheSame(oldItem: Hour, newItem: Hour): Boolean {
        return …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-recyclerview android-asynclistdiffer android-diffutils

4
推荐指数
1
解决办法
3031
查看次数

RecyclerView 未使用 SubmitList() 和 LiveData 自动刷新

情况如下:

我有一个RecyclerView正在Fragment使用DataBinding. 它的适配器是一个ListAdapter.

class MyFragment : Fragment() {
    override fun onCreateView(...) {
        val binding = // inflate layout with DataBindingUtil

        val myListAdapter = MyListAdapter()
        binding.recyclerView.adapter = myListAdapter

        val myViewModel: MyViewModel by activityViewModels()
        myViewModel.myLiveData.observe(viewLifecycleOwner, Observer {
            println("before submit: ${myListAdapter.currentList}")
            myListAdapter.submitList(it)
            println("after submit: ${myListAdapter.currentList}")
        })

        return binding.root
    }
}
Run Code Online (Sandbox Code Playgroud)

要显示的数据由 表示List<Double>。设置后,列表将用于初始化 a,MutableLiveData如下所示:

class MyViewModel : ViewModel() {
    val data = listOf<Double>(/* init with some values */)
    val myLiveData = MutableLiveData(data) …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-recyclerview android-livedata android-diffutils

4
推荐指数
1
解决办法
2895
查看次数

由于 ItemTouchHelper 和 DiffUtil 之间的冲突而出现不需要的动画

我正在实现一个带有拖放支持的 RecyclerView。当删除某个项目时,该项目的索引列将在 Room 数据库中更新以存储更新的排序。

我面临的问题是,当我在删除项目后调用 Room 数据库更新时,因为项目列表是 ViewModel 中的 LiveData 并通过数据绑定绑定到 RecyclerView,DiffUtil 将立即重新计算项目位置和内容,其中 1 . 添加新的不需要的动画,并且 2. 有时内容无法正确刷新。

项目触摸助手:

val helper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP or ItemTouchHelper.DOWN or
            ItemTouchHelper.START or ItemTouchHelper.END, 0
) {

    var dragFrom = -1
    var dragTo = -1

    override fun onMove(
        recyclerView: RecyclerView, selected: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        val from = selected.adapterPosition
        val to = target.adapterPosition

        if (dragFrom == -1) {
            dragFrom = from
        }
        dragTo = to
        recyclerView.adapter?.notifyItemMoved(from, to)

        return true
    } …
Run Code Online (Sandbox Code Playgroud)

android android-recyclerview itemtouchhelper android-diffutils

4
推荐指数
1
解决办法
1061
查看次数

如何在 Android 上的 RecyclerViewAdapter 中使用 DiffUtils

在我的应用程序中,我想使用RecyclerView适配器并设置我使用的数据DiffUtils
我想从服务器搜索数据然后将其显示到RecyclerView
我写了下面的代码,但是搜索数据后显示项目重叠!
我想先清除以前的数据,然后添加新项目!

片段代码:

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    //InitViews
    binding.apply {
        searchEdt.addTextChangedListener {
            val search = it.toString()
            if (search.isNotEmpty()) {
                viewModel.searchList.observe(viewLifecycleOwner) { response ->
                    lastMoviesAdapter.differ.submitList(response.data)
                    searchMoviesRecycler.initRecycler(LinearLayoutManager(requireContext()), lastMoviesAdapter)
                }
                viewModel.loadSearchMovies(search)
            } else {
                Snackbar.make(view, getString(R.string.fillAllFields), Snackbar.LENGTH_SHORT).show()
            }
        }
Run Code Online (Sandbox Code Playgroud)

适配器代码:

    class LastMoviesAdapter @Inject constructor() : RecyclerView.Adapter<LastMoviesAdapter.ViewHolder>() {

    private lateinit var binding: ItemHomeMoviesLastBinding

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        binding = ItemHomeMoviesLastBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder()
    } …
Run Code Online (Sandbox Code Playgroud)

android android-recyclerview android-diffutils

4
推荐指数
1
解决办法
5129
查看次数