Android开发:SwipeMenuListView删除Item异常问题求助
问题描述
您好,我遇到了一个无法解决的问题,恳请您的帮助。我尝试删除SwipeMenuListView中的Item,但未能成功,相关代码如下:
list= (SwipeMenuListView) findViewById(R.id.listView1); groups = new UserData(getApplication()).getUserGroups(); if (groups == null) groups = new ArrayList<String>(); adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, groups.toArray(new String[0])); list.setAdapter(adapter); list.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(int position, SwipeMenu menu, int index) { switch (index) { case 0: try { groups.remove(position); adapter.notifyDataSetChanged(); Log.d("TAG","onMenuClickListener"+index+" position is "+ position); break; } catch (Exception e) { Log.d("TAG","error " + e); } } // false : close the menu; true : not close the menu return false; } }); list.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(GroupActivity.this, MapsActivity.class); intent.putExtra("GRUPID", groups.get(position)); startActivity(intent); } });
当我尝试删除Item时,该Item并未消失,再次点击删除按钮时出现以下错误:
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1.
我推测Item实际上已被删除,但仍在界面上显示。再次感谢您的帮助。
问题分析与解决方案
我来帮你拆解下这个问题:你之所以遇到删除后界面不更新、第二次点击还报索引越界的情况,核心原因是你创建ArrayAdapter时用了groups.toArray(new String[0]),这相当于给Adapter传了一个和原始groups集合完全独立的新数组。也就是说,Adapter内部维护的数据源和你后续修改的groups根本不是同一个对象——你删了groups里的元素,但Adapter里的数据还是原来的,所以调用notifyDataSetChanged()也没用,界面当然不会更新。等第二次点击时,界面上显示的还是旧的Item位置,但groups已经少了一条,自然就会出现索引越界的错误。
解决起来很简单,只需要改一行代码:把ArrayAdapter的初始化方式改成直接传入原始的groups集合,而不是转成数组:
// 原来的代码 adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, groups.toArray(new String[0])); // 修改后的代码 adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, groups);
这样ArrayAdapter就会直接关联groups这个ArrayList,当你调用groups.remove(position)后,再调用adapter.notifyDataSetChanged(),Adapter就能立刻感知到数据变化,界面也会同步更新,索引越界的问题也会随之消失。
另外给你个小优化建议:如果你的列表项比较多,删除Item时可以用adapter.notifyItemRemoved(position)替代notifyDataSetChanged(),前者只会刷新被删除位置及之后的Item,效率更高;当然如果你的列表比较简单,用notifyDataSetChanged()也完全没问题。
内容的提问来源于stack exchange,提问作者Oğuzhan ÖZCAN

