【问题标题】:RecyclerView ItemDecoration and Iterator.remove() problemsRecyclerView ItemDecoration 和 Iterator.remove() 问题
【发布时间】:2016-09-21 01:59:10
【问题描述】:

我有一个带有如下物品装饰的 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;
        }
    }
}

每 10 秒,我将遍历此回收器视图中的数据并调用 iterator.remove()。在那之后,我通知适配器该项目已被删除。但是,在删除该项目后,getItemOffsets() 会为该回收站视图调用两次。第一次显示 1 个子视图,这是正确的,因为我删除了一个。但在那之后,它再次被调用并报告 2 个子视图。这仅在移除项目时发生。这是什么原因造成的?

我是这样迭代的:

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() + "\"");
                                        }
                                    }
                                }

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()));
        }
    });
}

这是 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

注意:使用notifyDataSetChanged() 代替notifyItemRemoved() 有效,但动画不显示。

【问题讨论】:

    标签: java android iterator android-recyclerview


    【解决方案1】:

    我已通过将 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;
        }
    }
    

    调用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
    

    删除第一项后,日志是:

    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
    

    很明显,在调用notifyItemRemoved 之后,它并没有正确地从回收器视图中删除视图,而是最后而不是第一个更新它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 2016-05-02
      • 2019-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多