为什么列表更改会触发整个列表

Why list changes fires on whole list

当 firestore 数据库中的项目发生变化时,我将 mvp 与存储库一起使用以更新 recyclerview 上的项目。

根据要求,这是来自 SharedModelClass 的更多代码:

   public LiveData<List<Task>> tasksListening() {
        return repository.tasksListening(false);
    }

这导致:

   public LiveData<List<Task>> tasksListening(boolean b) {
            return new FirestoreTasksData(tasksReference, b);
    }

这是 FirestoreTasksData extends LiveData:

public class FirestoreTasksData extends LiveData<List<Task>> {

    List<Task> tasks;

         for (QueryDocumentSnapshot doc : value) {
                Task item = doc.toObject(Task.class);
                tasks.add(item);
         }
 
        setValue(tasks);


    };
}

所有工作都很完美,除了即使更新一个项目,列表也会整体更新。

sharedViewModel.tasksListening().observe(getViewLifecycleOwner(), tasks -> {
            tasksAdapter.submitList(tasks);
        });

这里是适配器代码:

    public class MyTasksAdapter extends RecyclerView.Adapter<MyTasksAdapter.TaskHolder> {
    
        private final AsyncListDiffer<Task> mDiffer = new AsyncListDiffer<>(this, DIFF_CALLBACK);
    
        private static final DiffUtil.ItemCallback<Task> DIFF_CALLBACK = new DiffUtil.ItemCallback<Task>() {
            @Override
            public boolean areItemsTheSame(@NonNull Task oldItem, @NonNull Task newItem) {
                return oldItem.getId().equals(newItem.getId());
            }
    
            @Override
            public boolean areContentsTheSame(@NonNull Task oldItem, @NonNull Task newItem) {
                return oldItem.geteDate().equals(newItem.geteDate()) && (new HashSet<>(oldItem.getRoles().values()).equals(new HashSet<>(newItem.getRoles().values())));
            }
        };
    }

public void submitList(List<Task> list) {
          mDiffer.submitList(list);
      }

    @Override
    public int getItemCount() {
        return mDiffer.getCurrentList().size();
    }

这是错误还是功能?我之前使用过 Firestore UI 回收器适配器,刚决定重构代码。

这是预期的行为。当 query/collection 的结果发生任何变化时,您的代码将被调用,其中包含与 query/collection.

匹配的所有变化的 QuerySnapshot object

如果您想查看更改的内容,可以查看快照的 getDocumentChanges() 以查看这些内容。有关此(和示例)的更多信息,请参阅 viewing change between snapshots.

上的文档

而不是实现自定义适配器和 DiffUtil 回调。

看看LiveAdapter

你只需要在Gradle中添加最新的依赖即可。

dependencies {
    implementation 'com.github.RaviKoradiya:LiveAdapter:1.3.2-1608532016'
    // kapt 'com.android.databinding:compiler:GRADLE_PLUGIN_VERSION' // this line only for Kotlin projects
}

并将适配器与您的 RecyclerView 绑定

LiveAdapter(
            data = liveListOfItems,
            lifecycleOwner = this@MainActivity,
            variable = BR.item )
            .map<Header, ItemHeaderBinding>(R.layout.item_header) {
                areContentsTheSame { old: Header, new: Header ->
                    return@areContentsTheSame old.text == new.text
                }
            }
            .map<Point, ItemPointBinding>(R.layout.item_point) {
                areContentsTheSame { old: Point, new: Point ->
                    return@areContentsTheSame old.id == new.id
                }
            }
            .into(recyclerview)

就是这样。适配器实现无需额外编写代码,观察LiveData并通知适配器。

想删除post但是规则。

我解决了这个问题。问题是一切正常。如果需要,请随意使用代码。

刚刚发现observer内部调用了另外一个方法,所以看到渲染效果好像adapter有bug

sharedViewModel.tasksListening().observe(getViewLifecycleOwner(), tasks -> {
            tasksAdapter.submitList(tasks);
              checkEmpty(tasks.size());
        });



 private void checkEmpty(int size) {

        if (size == 0) {
            crossFade(noDataLayout, mTasksRecycler);
        } else {
            crossFade(mTasksRecycler, noDataLayout);

        }
    }

我修复了这个问题,现在一切正常。