[英]RecyclerView ItemDecoration and Iterator.remove() problems
I have a recyclerView with an item decoration like this: 我有一个带有项目装饰的recyclerView,如下所示:
public class VerticalItemDecoration extends RecyclerView.ItemDecoration{
private int space;
public VerticalItemDecoration(int space){
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state){
outRect.top = space;
Log.e("Decor", "Parent: " + parent + " Childs: " + parent.getChildCount());
if (parent.getChildLayoutPosition(view) == 0){
outRect.top = 0;
}
}
}
Every 10 seconds, i am iterating through the data in this recycler view and calling iterator.remove()
. 每隔10秒,我就会在此回收器视图中遍历数据并调用iterator.remove()
。 Right after that, i am notifying the adapter that the item was removed. 之后,我通知适配器该项目已删除。 However after removing the item, getItemOffsets()
is called twice for that recycler view. 但是,删除该项目后,该回收者视图将两次调用getItemOffsets()
。 The first time it shows 1 child view, which is correct because i removed one. 第一次显示1个子视图,这是正确的,因为我删除了一个。 But right after that it gets called again and reports 2 child views. 但是之后立即再次调用它并报告2个子视图。 This is only happening when removing items. 这仅在删除项目时发生。 What is causing this? 是什么原因造成的?
I am iterating like this: 我这样迭代:
for (Iterator<Client> iterator = AdapterClients.listClients.iterator(); iterator.hasNext();){
Client client1 = iterator.next();
if (client.getMacAddress().equals(client1.getMacAddress())){
//This client is already on the adapter
clientExists = true;
//Make sure the client is still reachable
if (ApManager.isClientReachable(client1, 3000)){
//Client is still reachable
//Update the client's information
if (client1.getHostName().equals("Unknown Host Name")){
client1.setHostName(ApManager.getHostName(client1));
notifyAdapter("itemChanged", AdapterClients.listClients.indexOf(client1));
}
}else{
//Client is no longer reachable, remove it from the adapter
int index = AdapterClients.listClients.indexOf(client1);
iterator.remove();
Log.e("Arp", "index: " + index + " objIndex: " + AdapterClients.listClients.indexOf(client1));
notifyAdapter("itemRemoved", index);
DataLogger.log("Client " + client1.getIpAddress() + " disconnected from \"" + ApManager.getActiveHotspot().getSsid() + "\"");
}
}
}
The notifyAdapter()
method looks like this: notifyAdapter()
方法如下所示:
private static void notifyAdapter(final String action, final int index){
new Handler(Looper.getMainLooper()).post(new Runnable(){
@Override
public void run(){
switch (action){
case "itemInserted":
Log.e("Arp", "itemInserted");
FragmentClients.adapterClients.notifyItemInserted(index);
break;
case "itemRemoved":
Log.e("Arp", "itemRemoved");
FragmentClients.adapterClients.notifyItemRemoved(index);
Log.e("Arp", "after itemRemoved");
break;
//Other cases...
}
FragmentClients.updateText();
//FragmentClients.adapterClients.notifyItemChanged(0);
FragmentHotspots.adapterHotspots.notifyItemChanged(AdapterHotspots.listHotspots.indexOf(ApManager.getActiveHotspot()));
}
});
}
This is the output from logcat: 这是logcat的输出:
05-23 18:58:57.143 4726-5658/com.example E/Arp: index: 0 objIndex: -1
05-23 18:58:57.154 4726-4726/com.example E/Arp: itemRemoved
05-23 18:58:57.154 4726-4726/com.example E/Arp: after itemRemoved
05-23 18:58:57.171 4726-4726/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{b0a533b VFED.... .F....I. 0,0-1080,1509 #7f0e009b app:id/recyclerViewClients} Childs: 1
05-23 18:58:57.174 4726-4726/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{b0a533b VFED.... .F....I. 0,0-1080,1509 #7f0e009b app:id/recyclerViewClients} Childs: 2
05-23 18:58:57.187 4726-4726/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{3d927634 VFED.... ......I. 0,0-1080,1509 #7f0e009d app:id/recyclerViewHotspots} Childs: 1
NOTE: Using notifyDataSetChanged()
instead of notifyItemRemoved()
works, but then the animation doesn't show. 注意:使用notifyDataSetChanged()
而不是notifyItemRemoved()
可以,但是动画不会显示。
I have fixed this by changing the getItemOffsets()
method to this 我已经通过将getItemOffsets()
方法更改为此方法来解决此问题
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state){
outRect.top = space;
Log.e("Decor", "Parent: " + parent + " Childs: " + parent.getChildCount() + " pos: " + parent.getChildLayoutPosition(view));
if (parent.getChildCount() == 1){
outRect.top = 0;
}
}
It seems like the views are updating in the wrong order when calling notifyItemRemoved()
because during initialization the log is: 似乎在调用notifyItemRemoved()
时视图以错误的顺序更新,因为初始化期间日志为:
05-23 20:51:56.889 14129-14129/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{323b3d54 VFED.... ......ID 0,0-1080,1845 #7f0e009d app:id/recyclerViewHotspots} Childs: 1 pos: 0
05-23 20:51:56.895 14129-14129/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{323b3d54 VFED.... ......ID 0,0-1080,1845 #7f0e009d app:id/recyclerViewHotspots} Childs: 2 pos: 1
05-23 20:51:56.899 14129-14129/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{323b3d54 VFED.... ......ID 0,0-1080,1845 #7f0e009d app:id/recyclerViewHotspots} Childs: 3 pos: 2
and after deleting the first item the log is: 删除第一项后,日志为:
05-23 20:52:15.498 14129-14129/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{323b3d54 VFED.... .F....I. 0,0-1080,1509 #7f0e009d app:id/recyclerViewHotspots} Childs: 1 pos: 1
05-23 20:52:15.499 14129-14129/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{323b3d54 VFED.... .F....ID 0,0-1080,1509 #7f0e009d app:id/recyclerViewHotspots} Childs: 2 pos: 2
05-23 20:52:15.499 14129-14129/com.example E/Decor: Parent: android.support.v7.widget.RecyclerView{323b3d54 VFED.... .F....ID 0,0-1080,1509 #7f0e009d app:id/recyclerViewHotspots} Childs: 3 pos: 0
So clearly after calling notifyItemRemoved
, it doesn't properly remove the view from the recycler view and it updates it last instead of first. 很明显,在调用notifyItemRemoved
,它没有正确地从回收器视图中删除该视图,并且它最后而不是首先更新它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.