2

私はAndroid 3.1アプリケーションを開発しています。ArrayListの要素を削除するとArrayAdapterでIndexOutOfBoundsExceptionがスローされます

私は自分のカスタムArrayAdapterを持っています。 ListViewに名前のリストを表示したい。

これらの名前は、ローカルでダウンロードして保存できる形式です。ユーザーが1つまたは複数のファイルをダウンロードして保存すると、私は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; 
    } 
} 

私は、フォーム上の3つの項目があったが、私はそれらの1つを削除します。

なぜ例外が表示されますか?

これは例外ログである:

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

+0

フォームはAsyncTaskで初期化されます。 – VansFannel

+1

私はここでそれを見ていないが、私はあなたがgetCount()をオーバーライドしていると仮定していますか? – Shubhayu

答えて

7

オーバーライド同様にgetCountを()。それに値forms.size()を返します。

+0

ちょっと仲間+1私の側からそれは本当に働く................ – itechDroid

2

位置は、配列インデックスがゼロに基づいている間に基づくものです。

だから、その行に変更:

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

最初のListViewアイテムを選択すると、checkedItemsPositionには0が含まれます。 – VansFannel

+0

@WarrenFaithこれはここでどのように適用されるかわかりません。この場合の「i」は0〜forms.size()-1です。私はこの1/0のチェックが必要ないと思う。何か不足していますか? – Shubhayu

1

Listsとそのインデックスの2つを使用していますが、これらのリストは決して同期されません(別のものを確認せずに個別に変更できます)。

なぜ代わりに、あなたはuncheckedFormsからフォームへの参照を削除し、同期の両方List年代を保つことになるcheckedFormsに追加することができ、ArrayList<Form> checkFormsArrayList<Form> uncheckedFormsを使用していません。

すべてのフォームを取得する必要があるときは、単にArrayListの両方のユニオンを返すことができます。

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

0

なぜ例外が表示されているのですか?彼の質問はかなり古くても、私はここで答えを提供します。

「フォーム」を更新するときに、新しい配列オブジェクト(したがって新しい参照)を作成し、ArrayAdapterが独自の配列オブジェクトを保持している間にフォームの参照を変更するためですmObjects:コンストラクタは、指定した配列オブジェクト(オブジェクト)の参照をコピーします。あなたはソースコードを見ればこれを見ることができます(良いことはオープンソースです)。

本当に問題を解決するには、継承された関数add(...)、addAll(...)などを使用して配列を更新する必要があります。または、単にbaseadapterを拡張して独自の実装を作成してください。

関連する問題