最近项目中遇到了一个比较有趣的问题。
项目里有一些老代码使用的不是RecyclerView而是ListView。在更新界面过程中,涉及到数据的查询,于是开启了一个线程池去查询。
查询的调用是这样的FileSizeUtil.getInstance().setDirLabel(mContext, f, vh.info);
vh.info就是在ViewHolder中保存的TextView用来展示查询到的数据。然后界面的现象是,更新的数据第一行总是有误。
于是我在更新界面的地方加入了打印vh.info 以及查询结果的打印
Line 1659: 11-01 20:27:47.912 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/amap
Line 1671: 11-01 20:27:47.917 11295 11295 I zhang5555: positon 4 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1672: 11-01 20:27:47.917 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/Android
Line 1681: 11-01 20:27:47.923 11295 11295 I zhang5555: positon 5 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1682: 11-01 20:27:47.923 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/backups
Line 1690: 11-01 20:27:47.928 11295 11295 I zhang5555: positon 6 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1691: 11-01 20:27:47.928 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/bcr
Line 1699: 11-01 20:27:47.933 11295 11295 I zhang5555: positon 7 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1700: 11-01 20:27:47.933 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/Browser
Line 1708: 11-01 20:27:47.939 11295 11295 I zhang5555: positon 0 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1709: 11-01 20:27:47.939 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/1
Line 1717: 11-01 20:27:47.944 11295 11295 I zhang5555: positon 1 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1718: 11-01 20:27:47.944 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/123
Line 1724: 11-01 20:27:47.946 11295 11295 I zhang5555: positon 2 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1727: 11-01 20:27:47.947 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/Alarms
Line 1730: 11-01 20:27:47.948 11295 11295 I zhang5555: positon 3 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1731: 11-01 20:27:47.949 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/amap
Line 1737: 11-01 20:27:47.951 11295 11295 I zhang5555: positon 4 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1740: 11-01 20:27:47.951 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/Android
Line 1754: 11-01 20:27:47.953 11295 11295 I zhang5555: positon 5 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1756: 11-01 20:27:47.953 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/backups
Line 1763: 11-01 20:27:47.956 11295 11295 I zhang5555: positon 6 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
Line 1764: 11-01 20:27:47.956 11295 11295 I zhang5566666: TextView android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info} path /storage/emulated/0/bcr
Line 1770: 11-01 20:27:47.958 11295 11295 I zhang5555: positon 7 VIEWHOLDER android.widget.TextView{3b6ae2a V.ED..... ......ID 0,0-0,0 #7f0600e1 app:id/dir_list_info}
简单说下这个打印的内容 position是 在listview展示的位置,VIEWHOLDER android.widget.TextView{3b6ae2a这里是穿进去的TextView控件直接打印,这样可以区分是哪个TextView对象。 这是截取的有问题的一部分,可以发现更新的都是同一个TextView。
这里自己思考了一下 因为我的查询是开启了线程去查询,结束后在更新到界面的。 应该是由于在这个过程中ViewHolder 被复用了。比如 在开启线程查询时 是 在第一行位置发出的查询,等到查询结束。 这个传入的ViewHolder.TextView 已经不在当时的第一行了(因为在其他行被复用了)。所以导致了界面上展示的数据有误。
好了,说一下解决办法。就是利用View的setTag 和getTag。 放到我这个问题上是这样的,因为我展示的内容是根据一个文件的路径去查询其子文件夹的数量,并把数量展示出来。 那我们就可以在传入时
vh.info.setTag(path);
FileSizeUtil.getInstance().setDirLabel(mContext, f, vh.info);
path 是路径。
等到更新内容时加入判断,
if (str != null && infoView.getTag().equals(path)){
infoView.setText(str);
}
在判断时的这个path 是你在开启线程查询时保存的。 利用这个判断 就可以避免数据更新到变更位置后的ViewHolder上。
当然 在我这个问题中使用的是path ,大家要根据自己的问题找到这个每行数据独特的地方去保存在tag中,后面在取出判断。
这个独特的地方就类似于数据库中的主键一样。