Android 为什么列表更改会触发整个列表
当firestore数据库中的项目发生变化时,我正在使用mvp with repository更新recyclerview上的项目 如前所述,以下是来自SharedModelClass的更多代码:Android 为什么列表更改会触发整个列表,android,google-cloud-firestore,android-livedata,Android,Google Cloud Firestore,Android Livedata,当firestore数据库中的项目发生变化时,我正在使用mvp with repository更新recyclerview上的项目 如前所述,以下是来自SharedModelClass的更多代码: public LiveData<List<Task>> tasksListening() { return repository.tasksListening(false); } 下面是适配器代码: public class MyTask
public LiveData<List<Task>> tasksListening() {
return repository.tasksListening(false);
}
下面是适配器代码:
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();
}
公共类MyTasksAdapter扩展了RecyclerView.Adapter{
private final AsyncListDiffer mDiffer=新的AsyncListDiffer(这是DIFF_回调);
私有静态final DiffUtil.ItemCallback DIFF_CALLBACK=new DiffUtil.ItemCallback(){
@凌驾
公共布尔值AreItemsSame(@NonNull任务oldItem,@NonNull任务newItem){
返回oldItem.getId().equals(newItem.getId());
}
@凌驾
公共布尔值是相同的内容(@NonNull Task oldItem、@NonNull Task newItem){
返回oldItem.geteDate().equals(newItem.geteDate())&&(新哈希集(oldItem.getRoles().values()).equals(新哈希集(newItem.getRoles().values()));
}
};
}
公共无效提交列表(列表){
mDiffer.提交列表(列表);
}
@凌驾
public int getItemCount(){
返回mDiffer.getCurrentList().size();
}
这是一个bug还是一个特性?我以前使用Firestore UI回收器适配器,只是决定重构代码。这是预期行为。当查询/集合的结果发生任何更改时,您的代码将被调用,其中包含与查询/集合匹配的所有更改
如果要查看发生了哪些更改,可以查看快照的
getDocumentChanges()
,查看这些更改。有关这方面的更多信息(以及示例),请参阅。上的文档,而不是实现自定义适配器和DiffUtil回调
看一看
您只需要在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)
LiveAdapter(
数据=liveListOfItems,
生命周期所有者=this@MainActivity,
变量=BR.item)
.地图(右布局.项目标题){
内容是否相同{old:Header,new:Header->
return@areContentsTheSameold.text==new.text
}
}
.地图(右布局图项目\ U点){
内容是否相同{旧:点,新:点->
return@areContentsTheSameold.id==new.id
}
}
.进入(回收视图)
就这样。无需为适配器实现编写额外代码,请观察LiveData并通知适配器。希望删除post,但不删除规则 我解决了这个问题。问题是,所有的工作都很好。如果需要,可以随意使用代码 我刚刚意识到,inside observer调用了另一个方法,这就是我看到渲染效果的原因,就好像适配器存在一些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);
}
}
我解决了这个问题,现在一切正常。FirestoreTasksData的代码看起来不完整,因为没有构造函数或方法。还不清楚您是如何使用它的,或者Firestore查询来自何处。请编辑该问题以显示重现该问题的。已使用一些代码更新。你在这方面有什么进展吗?下面有三个人试图帮助你。你有机会检查他们的答案吗?如果答案有用,请单击向上投票按钮(▲) 如果它回答了您的问题,请单击复选标记(✓) 接受它。这样其他人就知道你得到了(足够)的帮助。另请参见LiveData只有一个方法setValue。如果项发生更改,我应该只将这些项添加到列表中并传递它。这不起作用。以前添加的项将被删除。您可以通过查看
getDocumentChanges()来确定添加了什么
如我链接的文档所示。但您也可以简单地清除现有列表,然后使用此处显示的代码重新填充其中一个:
dependencies {
implementation 'com.github.RaviKoradiya:LiveAdapter:1.3.2-1608532016'
// kapt 'com.android.databinding:compiler:GRADLE_PLUGIN_VERSION' // this line only for Kotlin projects
}
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)
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);
}
}