【发布时间】:2021-10-07 05:32:26
【问题描述】:
我正在使用带有回收器视图的列表适配器,现在数据类包含一个变量 isChecked,这用于指示用户是否选择了此变量,代码正在更新列表,因为我可以看到日志(我为了测试目的而放置的)返回当前列表总是在用户单击一个项目时更新,但由于某种原因,UI 中的更改(基于 isChecked 变量)仅在滚动回收器视图或单击其他项目时反映.我放了一个 notifyDataSetChanged 来查看它是否强制列表更新并查看更新的视图是否正确并且它是否有效,但这会破坏使用 diff util 的整个目的。我的包装数据类中有一个嵌套列表,它在 diff util 中进行比较,如下所示
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<MainDataClass>() {
override fun areItemsTheSame(
oldItem: MainDataClass,
newItem: MainDataClass
): Boolean {
if (oldItem is MainDataClass.Item && newItem is MainDataClass.Item) {
return oldItem.data.id == newItem.data.id
} else if (oldItem is MainDataClass.List && newItem is MainDataClass.List) {
return oldItem.list == newItem.list
} else return false
}
override fun areContentsTheSame(
oldItem: MainDataClass,
newItem: MainDataClass
): Boolean {
if (oldItem is MainDataClass.Item && newItem is MainDataClass.Item) {
return oldItem.data == newItem.data
} else if (oldItem is MainDataClass.List && newItem is MainDataClass.List) {
return oldItem.list == newItem.list
} else return false
}
}
MainDataClass.List 包含上述特定项目的列表。
public class Item{
private Integer count;
private Integer id;
private String icon_img;
private String name;
private String cover_img;
private String group_name;
private Integer parent_id;
private Integer status;
private boolean checked = false;
private Integer whatToVisible;
public Item(Integer count, Integer id, String icon_img, String cover_img, String group_name, Integer parent_id) {
this.count = count;
this.id = id;
this.icon_img = icon_img;
this.cover_img = cover_img;
this.group_name = group_name;
this.parent_id = parent_id;
this.checked = false;
}
public Item(Integer id, String icon_img, String group_name, Integer parent_id, boolean checked) {
this.id = id;
this.icon_img = icon_img;
this.name = name;
this.group_name = group_name;
this.parent_id = parent_id;
this.checked = checked;
}
public Item(Integer id,Integer parent_id) {
this.id = id;
this.parent_id = parent_id;
}
public static Item objectExample() {
return new TrendingGroupsResponse(-2, -2);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getCount() {
return count;
}
public String getIcon_img() {
return icon_img;
}
public void setIcon_img(String icon_img) {
this.icon_img = icon_img;
}
public String getCover_img() {
return cover_img;
}
@Override
public int hashCode() {
return this.id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Item)) return false;
Item that = (Item) o;
return checked == that.checked && Objects.equals(count, that.count) && Objects.equals(id, that.id) && Objects.equals(icon_img, that.icon_img) && Objects.equals(name, that.name) && Objects.equals(cover_img, that.cover_img) && Objects.equals(group_name, that.group_name) && Objects.equals(parent_id, that.parent_id) && Objects.equals(status, that.status) && Objects.equals(whatToVisible, that.whatToVisible);
}
@Override
public String toString() {
return "id: " + this.id;
}
public void setCover_img(String cover_img) {
this.cover_img = cover_img;
}
public String getGroup_name() {
if (name != null){
group_name = name;
}
return group_name;
}
public void setGroup_name(String group_name) {
this.group_name = group_name;
}
public Integer getParent_id() {
return parent_id;
}
public void setParent_id(Integer parent_id) {
this.parent_id = parent_id;
}
public void setCount(Integer count) {
this.count = count;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getIconImg() {
return icon_img;
}
public void setIconImg(String icon_img) {
this.cover_img = icon_img;
}
public String getCoverImg() {
return cover_img;
}
public void setCoverImg(String cover_img) {
this.cover_img = cover_img;
}
public String getGroupName() {
if (name != null) {
group_name = name;
}
return group_name;
}
public void setGroupName(String group_name) {
this.group_name = group_name;
}
public Integer getWhatToVisible() {
return whatToVisible;
}
public void setWhatToVisible(Integer whatToVisible) {
this.whatToVisible = whatToVisible;
}
从主列表中单击主项时调用的方法
fun addOrRemoveSelectedItemsIfPresent(item: Item) {
viewModelScope.launch {
addOrRemoveItemsFromPopularItems(item.id.toString())
updateAllItems(item)
var itemList = _selectedItems.value
if (itemList == null) itemList = ArrayList()
itemList.forEach { item1: Item ->
if (item1.id == item.id) {
itemList.remove(group)
selectedItemCount.set(selectedItemCount.get() - 1)
_selectedItems.value = itemList
return@launch
}
}
itemList.add(response)
selectedItemCount.set(selectedItemCount.get() + 1)
_selectedItems.value = itemList
}
}
private fun addOrRemoveItemsFromPopularItems(id: String) {
val popularItems = _popularItemsLiveData.value?.data
popularItems?.forEach {
if (it.id.toString() == id) {
if (it.isChecked == null || it.isChecked == false) {
it.isChecked = true
} else {
it.isChecked = false
}
}
}
_popularItemsLiveData.postValue(Success(popularItems))
}
【问题讨论】:
-
发布您的 MainDataClass 和子项目
-
@MartinMarconcini 我不能因为它不能透露,对不起,但我可以说它 MainDataClass 是一个密封类,包含一个项目的数据类和另一个具有列表的数据类项目
-
我的意思是,您可以发布您的数据类、更改名称并显示您正在使用的数据类型的基本信息。如果您将两个列表与 kotlin 中的两个数据类进行比较,您将得到不同的结果,但如果您在这里比较不同的类型(正如您的
if语句所证明的那样),我不确定 DiffUtil 会如何反应.或者,查看DiffUtil's Source Code ;) -
最后,你调试好了吗?您可以在该 diffUtil 中放置断点,模拟一个小型数据集并进行比较,或者甚至更好地编写一个单元测试来展示 which 案例失败。我的意思是this simple comparison 显示了它如何检测列表中的项目何时不同,因此您的问题出在其他地方。
-
@MartinMarconcini 一切都正确,diff util 正在按预期工作,问题出现在这里,有一个名为 isChecked 的布尔值,用于查看是否选择了该项目,默认情况下它是值为 false,并在更新列表的 viewModel 中更新,此列表的观察者再次提交列表,但是当我比较新旧项目的 isChecked 值时,两者都显示为 true(仅适用于所选组)跨度>