2

私はAndroid3.1アプリケーションを開発しています。

カスタム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)
4

5 に答える 5

7

getCount()をオーバーライドします。そして、その中に値forms.size()を返します。

于 2012-04-18T10:03:13.807 に答える
5

私の場合、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);
}

...
于 2013-06-11T13:27:07.917 に答える
2

位置は1ベースですが、配列インデックスは0ベースです。

したがって、その行を変更します。

if (!checkedItemsPosition.contains(new Integer(i)))
    copyForms.add(forms.get(i - 1));
于 2012-04-18T09:59:32.390 に答える
1

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

ArrayList<Form> checkForms代わりにとを使用しないのはなぜですかArrayList<Form> uncheckedForms。フォームへの参照をから削除してuncheckedForms追加するとcheckedForms、両方Listの同期が維持されます。

すべてのフォームを取得する必要がある場合は、両方ArrayListの和集合を返すだけです。

于 2012-04-18T10:05:36.533 に答える
0

なぜ彼が例外を取得しているのか、まだ誰も答えていません。それで、彼の質問はかなり古いですが、ここで私の答えを提供します。

例外が発生する理由は、「フォーム」を更新するときに、新しい配列オブジェクト(つまり新しい参照)を作成し、フォームの参照を変更する一方で、ArrayAdapterが独自の配列オブジェクトmObjectsを維持しているためです。コンストラクターは、指定した配列オブジェクト(オブジェクト)の参照をコピーします。ソースコードを調べると、これを確認できます(オープンソースであるのは良いことです)。

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

于 2013-10-25T13:56:04.467 に答える