2

我正在開發一個Android 3.1應用程序。刪除ArrayList上的元素在ArrayAdapter上拋出IndexOutOfBoundsException

我有我的自定義ArrayAdapter。我想在ListView中顯示一個名稱列表。

這些名稱是可以下載並在本地保存的表單。當用戶下載並保存一個或多個時,我撥打updateFormsNotDownloaded()。但是當我這樣做時,我得到一個IndexOutOfBoundsException。我認爲這個問題是因爲我打電話notifyDataSetChanged()

看我的代碼:

public class FormAdapter extends ArrayAdapter<Form> 
{ 
    private Context context; 
    private int layoutResourceId; 
    private List<Form> forms; 
    private ArrayList<Integer> checkedItemsPosition; 
    private Button downloadButton; 

    public ArrayList<Integer> getCheckedItemsPosition() 
    { 
     return checkedItemsPosition; 
    } 

    public String[] getSelectedFormsId() 
    { 
     String[] ids = new String[checkedItemsPosition.size()]; 
     int i = 0; 
     for(Integer pos : checkedItemsPosition) 
     { 
      Form f = forms.get(pos.intValue()); 
      ids[i] = f.FormId; 
      i++; 
     } 
     return ids; 
    } 

    /** 
    * Called when selected forms has been downloaded and save it locally correctly. 
    */ 
    public void updateFormsNotDownloaded() 
    { 
     ArrayList<Form> copyForms = new ArrayList<Form>(); 
     for (int i = 0; i < forms.size(); i++) 
     { 
      if (!checkedItemsPosition.contains(new Integer(i))) 
       copyForms.add(forms.get(i)); 
     } 
     forms = copyForms; 
     checkedItemsPosition.clear(); 
     notifyDataSetChanged(); 
    } 

    public FormAdapter(Context context, int textViewResourceId, 
      List<Form> objects, Button downloadButton) 
    { 
     super(context, textViewResourceId, objects); 

     this.context = context; 
     this.layoutResourceId = textViewResourceId; 
     this.forms = objects; 
     this.checkedItemsPosition = new ArrayList<Integer>(); 
     this.downloadButton = downloadButton; 
    } 

    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) 
    { 
     View row = convertView; 
     if (row == null) 
     { 
      LayoutInflater inflater = ((Activity)context).getLayoutInflater(); 
      row = inflater.inflate(layoutResourceId, parent, false); 
     } 

     Form f = forms.get(position); 
     if (f != null) 
     { 
      CheckBox checkBox = (CheckBox)row.findViewById(R.id.itemCheckBox); 
      if (checkBox != null) 
      { 
       checkBox.setText(f.Name); 
       checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() 
       { 
        public void onCheckedChanged(CompoundButton buttonView, 
          boolean isChecked) 
        { 
         //Form f = forms.get(position); 
         if (isChecked) 
         { 
          //checkedItems.add(f.FormId); 
          checkedItemsPosition.add(new Integer(position)); 
         } 
         else 
         { 
          //checkedItems.remove(checkedItems.indexOf(f.FormId)); 
          checkedItemsPosition.remove(checkedItemsPosition.indexOf(new Integer(position))); 
         } 
         downloadButton.setEnabled(checkedItemsPosition.size() > 0); 
        } 
       }); 
      } 
     } 

     return row; 
    } 
} 

我對形式的三個項目,但我刪除其中的一個。

爲什麼我得到那個異常?

這是異常日誌:

java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2 
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255) 
at java.util.ArrayList.get(ArrayList.java:308) 
at es.viacognita.adapters.FormAdapter.getView(FormAdapter.java:89) 
at android.widget.AbsListView.obtainView(AbsListView.java:1949) 
at android.widget.ListView.makeAndAddView(ListView.java:1756) 
at android.widget.ListView.fillDown(ListView.java:656) 
at android.widget.ListView.fillSpecific(ListView.java:1314) 
at android.widget.ListView.layoutChildren(ListView.java:1587) 
at android.widget.AbsListView.onLayout(AbsListView.java:1800) 
at android.view.View.layout(View.java:9581) 
at android.view.ViewGroup.layout(ViewGroup.java:3877) 
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1542) 
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1403) 
at android.widget.LinearLayout.onLayout(LinearLayout.java:1314) 
at android.view.View.layout(View.java:9581) 
at android.view.ViewGroup.layout(ViewGroup.java:3877) 
at android.widget.FrameLayout.onLayout(FrameLayout.java:400) 
at android.view.View.layout(View.java:9581) 
at android.view.ViewGroup.layout(ViewGroup.java:3877) 
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1542) 
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1403) 
at android.widget.LinearLayout.onLayout(LinearLayout.java:1314) 
at android.view.View.layout(View.java:9581) 
at android.view.ViewGroup.layout(ViewGroup.java:3877) 
at android.widget.FrameLayout.onLayout(FrameLayout.java:400) 
at android.view.View.layout(View.java:9581) 
at android.view.ViewGroup.layout(ViewGroup.java:3877) 
at android.view.ViewRoot.performTraversals(ViewRoot.java:1253) 
at android.view.ViewRoot.handleMessage(ViewRoot.java:2003) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:132) 
at android.app.ActivityThread.main(ActivityThread.java:4025) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:491) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599) 
at dalvik.system.NativeStart.main(Native Method) 
+0

**表單被初始化了嗎? – ngesh 2012-04-18 09:44:47

+0

表單在AsyncTask上初始化。 – VansFannel 2012-04-18 09:45:24

+1

我沒有看到它,但我假設你有overriden getCount()? – Shubhayu 2012-04-18 09:57:12

回答

7

覆蓋getCount將()。並返回值form.size()。

+0

嘿夥計+1從我這邊真的有效................ – itechDroid 2012-06-22 10:39:52

2

位置是一個基於而數組索引是基於零的。

因此改變該行:

if (!checkedItemsPosition.contains(new Integer(i))) 
    copyForms.add(forms.get(i - 1)); 
+0

當我選擇第一個ListView項目時,checkedItemsPosition包含0. – VansFannel 2012-04-18 10:22:18

+0

@WarrenFaith我似乎無法弄清楚這是如何適用的。在這種情況下,「我」是從0 - forms.size() - 1。我認爲我們不需要這裏1/0檢查。我錯過了什麼嗎? – Shubhayu 2012-04-18 10:23:28

1

您正在使用兩個Lists及其索引 - 但這些列表無法同步(它們可以單獨更改而不檢查其他列表)。

爲什麼不改用ArrayList<Form> checkFormsArrayList<Form> uncheckedForms,那麼你可以從uncheckedForms刪除引用到窗體並將其添加到checkedForms這將保留兩個List的同步。

當您需要獲取所有表格時,您可以簡單地返回ArrayList s的聯合。

4

在我的情況下,Shubhayu的答案是不夠的。 getCount和getItem必須是同步的,並使用相同的列表對象。如果您的陣列適配器必須使用內部的項目列表,則需要重寫。

public class MyArrayAdapter extends ArrayAdapter<MyItemType> { 

private final List<MyItemType> items; 

public MyArrayAdapter(final Context _context, final int _resource, final List<MyItemType> _items) { 
    super(_context, _resource, _items); 

    this.items = _items; 
} 

// IMPORTANT: either override both getCount and getItem or none as they have to access the same list 
@Override 
public int getCount() { 
    return this.items.size(); 
}; 

@Override 
public Site getItem(final int position) { 
    return this.items.get(position); 
} 

... 
+1

這應該是被接受的答案。重載'getCount'只是無效。 – Stan 2013-10-21 12:15:29

0

沒有人回答他爲什麼會得到例外。所以我會在這裏提供我的答案,儘管他的問題很古老。

你得到這個異常的原因是因爲當你更新「窗體」時,你創建一個新的數組對象(因此是一個新的引用)並且改變對它的引用,而ArrayAdapter維護它自己的數組對象mObjects,構造函數複製您提供的數組對象的引用(對象)。你可以看到它,如果你看看它的源代碼(它是開源的好東西)。

要真正解決問題,您應該使用繼承函數add(...),addAll(...)等來更新數組。或者只是擴展baseadapter並創建自己的實現。