欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

揭秘在ListView等AdapterView上動態(tài)添加刪除項的陷阱

 更新時間:2016年04月17日 15:41:41   投稿:lijiao  
今天遇到這么個需求,需要在運(yùn)行時動態(tài)添加ListView的item,看起來很簡單,實際操作過程中卻遇到了麻煩,下面揭秘在ListView等AdapterView上動態(tài)添加刪除項的陷阱

如何避開在ListView等AdapterView上動態(tài)添加刪除項的陷阱,下面就為大家分享,具體內(nèi)容如下

首先,定義如下array資源,作為列表的加載內(nèi)容:

<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設(shè)為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的代碼,似乎沒什么問題了,運(yùn)行一下。

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等方法在運(yùn)行時增刪列表項啊,那問題到底出在哪里呢?

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

  

  這里說到,如果要動態(tài)的改變列表的大小,必須使用一個可變大小的List(如ArrayList),而不能使用固定長度的array,否則將會得到UnsupportedOperationException。也就是說,由于需要從資源文件中加載內(nèi)容,所以我自然就想到調(diào)用ArrayAdapter.createFromResource(Context context, int textArrayResId, int textViewResId)方法來構(gòu)造adapter,而此方法導(dǎo)致ArrayAdapter中維護(hù)的是一個定長數(shù)組!對數(shù)組進(jìn)行add,當(dāng)然就會出錯了??吹竭@里我不禁感慨,好一個陷阱!?。≌嫦喾路痣x我越來越近了,讓我們再進(jìn)入ArrayAdapter源碼探個究竟。

public class ArrayAdapter<T> extends BaseAdapter implements Filterable {
   // 代表ArrayAdapter中的數(shù)據(jù)
 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();
 }
 }
 // 其他方法
}


  通過源碼可以發(fā)現(xiàn),我上面的思考還是有誤的。ArrayAdapter并沒有單獨維護(hù)array類型的數(shù)據(jù),而是統(tǒng)一轉(zhuǎn)換成了List,并存在了mObjects對象中?!   ?/p>

  createFromResource(...)調(diào)用了ArrayAdapter(Context context, int textViewResourceId, T[] objects)構(gòu)造方法,而在該方法的內(nèi)部實現(xiàn)中,android使用Arrays的靜態(tài)方法asList(...)將一個數(shù)組轉(zhuǎn)換為List。熟悉Java的程序員都知道,Arrays.asList(...)方法所返回的并不是一個java.util.ArrayList,而是一個Arrays類的內(nèi)部類,該List實現(xiàn)是不能進(jìn)行增刪操作的!!(見jdk文檔),對該List進(jìn)行add將拋出UnsupportedOperationException!

  哈哈,這下終于真相大白了,這樣一來稍微改動一下原來的代碼即可成功運(yùn)行: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("");
  }
 }
 };
}

以上就是關(guān)于Android Listview相關(guān)內(nèi)容介紹,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

最新評論