为什么列表更改会触发整个列表
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);
}
}
我修复了这个问题,现在一切正常。
当 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);
}
}
我修复了这个问题,现在一切正常。