当前位置: 移动技术网 > IT编程>移动开发>Android > 揭秘在ListView等AdapterView上动态添加删除项的陷阱

揭秘在ListView等AdapterView上动态添加删除项的陷阱

2019年07月24日  | 移动技术网IT编程  | 我要评论

讲泰国佛牌的小说,暴走装修网,涡阳门户

如何避开在listview等adapterview上动态添加删除项的陷阱,下面就为大家分享,具体内容如下

首先,定义如下array资源,作为列表的加载内容:

<resources>
 <string name="app_name">mylistview</string>
 <string-array name="language">
 <item>java</item>
 <item>c</item>
 <item>c++</item>
 <item>php</item>
 </string-array>

  然后简单地写下布局文件,由于我需要不管列表有多长,始终在底部显示编辑框和按钮,所以将listview中的layout_weight设为1。

<?xml version="1.0" encoding="utf-8"?>
<linearlayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <listview
 android:id="@android:id/list"
 android:layout_width="fill_parent"
 android:layout_height="0dip"
 android:layout_weight="1" />
 <linearlayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:orientation="horizontal">
 <edittext
  android:id="@+id/addlangedit"
  android:layout_width="200px"
  android:layout_height="wrap_content" />
 <button 
  android:id="@+id/addbutton"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="添加" />
 </linearlayout>
</linearlayout>

  最后添上activity的代码,似乎没什么问题了,运行一下。

public class mylistview extends listactivity {
 private arrayadapter<charsequence> madapter;
 private listview mlistview;
 private edittext mlanguagetext;
 private button maddbutton;
 
 /** called when the activity is first created. */
 @override
 public void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.mylist1);
 
 //get the view
 mlistview = getlistview();
 mlanguagetext = (edittext) findviewbyid(r.id.addlangedit);
 maddbutton = (button) findviewbyid(r.id.addbutton);
 
 //array adapter created from string array resources
 madapter = arrayadapter.createfromresource(
  this, 
  r.array.language, 
  android.r.layout.simple_list_item_1);
 //set the adapter
 mlistview.setadapter(madapter);
 
 //add listener
 maddbutton.setonclicklistener(monclicklistener);
 }
 
 private onclicklistener monclicklistener = new view.onclicklistener() {
 @override
 public void onclick(view v) {
  string text = mlanguagetext.gettext().tostring();
  if(null == text || "".equals(text.trim())) {
  toast.maketext(mylistview.this, "输入不能为空", toast.length_short).show();
  }else {
  madapter.add(text);
  madapter.notifydatasetchanged();
  mlanguagetext.settext("");
  }
 }
 };
}


  界面成功显示,可是每次点击“添加”,就会抛出java.lang.unsupportedoperationexception,这看似很匪夷所思,因为按照android的api文档,确实能通过adapter上的add、remove等方法在运行时增删列表项啊,那问题到底出在哪里呢?

  借助google的帮助,找到如下解答:

  

  这里说到,如果要动态的改变列表的大小,必须使用一个可变大小的list(如arraylist),而不能使用固定长度的array,否则将会得到unsupportedoperationexception。也就是说,由于需要从资源文件中加载内容,所以我自然就想到调用arrayadapter.createfromresource(context context, int textarrayresid, int textviewresid)方法来构造adapter,而此方法导致arrayadapter中维护的是一个定长数组!对数组进行add,当然就会出错了。看到这里我不禁感慨,好一个陷阱!!!真相仿佛离我越来越近了,让我们再进入arrayadapter源码探个究竟。

public class arrayadapter<t> extends baseadapter implements filterable {
   // 代表arrayadapter中的数据
 private list<t> mobjects;
 // 其他fields
 
 public arrayadapter(context context, int textviewresourceid, list<t> objects) {
 init(context, textviewresourceid, 0, objects);
 }

 public arrayadapter(context context, int textviewresourceid, t[] objects) {
 // 注意这里的arrays.aslist(...)方法!!!
 init(context, textviewresourceid, 0, arrays.aslist(objects)); 
 }

 public static arrayadapter<charsequence> createfromresource(context context,
  int textarrayresid, int textviewresid) {
 charsequence[] strings = context.getresources().gettextarray(textarrayresid);
 return new arrayadapter<charsequence>(context, textviewresid, strings);
 }

 private void init(context context, int resource, int textviewresourceid, list<t> objects) {
 mcontext = context;
 minflater = (layoutinflater)context.getsystemservice(context.layout_inflater_service);
 mresource = mdropdownresource = resource;
 mobjects = objects;
 mfieldid = textviewresourceid;
 }

 public void add(t object) {
 if (moriginalvalues != null) {
  synchronized (mlock) {
  moriginalvalues.add(object);
  if (mnotifyonchange) notifydatasetchanged();
  }
 } else {
  mobjects.add(object); // 若该mobjects为固定长度list,此处将抛异常!!!
  if (mnotifyonchange) notifydatasetchanged();
 }
 }
 // 其他方法
}


  通过源码可以发现,我上面的思考还是有误的。arrayadapter并没有单独维护array类型的数据,而是统一转换成了list,并存在了mobjects对象中。    

  createfromresource(...)调用了arrayadapter(context context, int textviewresourceid, t[] objects)构造方法,而在该方法的内部实现中,android使用arrays的静态方法aslist(...)将一个数组转换为list。熟悉java的程序员都知道,arrays.aslist(...)方法所返回的并不是一个java.util.arraylist,而是一个arrays类的内部类,该list实现是不能进行增删操作的!!(见jdk文档),对该list进行add将抛出unsupportedoperationexception!

  哈哈,这下终于真相大白了,这样一来稍微改动一下原来的代码即可成功运行:d
final solution:

/**
 * 
 * @author codingmyworld
 * 2011-7-31 下午04:43:48
 */
public class mylistview extends listactivity {
 private arrayadapter<charsequence> madapter;
 private listview mlistview;
 private edittext mlanguagetext;
 private button maddbutton;
 
 /** called when the activity is first created. */
 @override
 public void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.mylist1);
 
 //get the view
 mlistview = getlistview();
 mlanguagetext = (edittext) findviewbyid(r.id.addlangedit);
 maddbutton = (button) findviewbyid(r.id.addbutton);
 
 //array adapter created from string array resources
 list<charsequence> objects = new arraylist<charsequence>(
  arrays.aslist(getresources().gettextarray(r.array.language)));
 madapter = new arrayadapter<charsequence>(
  this, 
  android.r.layout.simple_list_item_1, 
  objects);
 //set the adapter
 mlistview.setadapter(madapter);
 
 //add listener
 maddbutton.setonclicklistener(monclicklistener);
 }
 
 private onclicklistener monclicklistener = new view.onclicklistener() {
 @override
 public void onclick(view v) {
  string text = mlanguagetext.gettext().tostring();
  if(null == text || "".equals(text.trim())) {
  toast.maketext(mylistview.this, "输入不能为空", toast.length_short).show();
  }else {
  madapter.add(text);
  madapter.notifydatasetchanged(); //not required 
  mlanguagetext.settext("");
  }
 }
 };
}

以上就是关于android listview相关内容介绍,希望对大家的学习有所帮助。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网