简体   繁体   中英

ArrayList Index Out Of Bound exception in android custom list view adapter

This is my below code , where my list looks like

position 1  |  image1      image2      image3
            ----------------------------------------
position 2  |  image1      image2      image3

I mean dynamically adding my images according to number of items in list for eg if my list has 21 items , then mylist populate 3 images in each position and totally 7 position gets created. My code is working fine

 public class ListViewAdapter extends BaseAdapter {
private static final String TAG = "Book-shelf";
private Activity activity;
private int totalBooks = 0;
private int bookItem = 0;
private int numberOfBookRows = 0;
private int extraBooks = 0;
int layoutId;
private int bookImage;
private ArrayList<HashMap<String, String>> dataList;
private static LayoutInflater inflater = null;

public ListViewAdapter(Activity a, int listRow,
        ArrayList<HashMap<String, String>> fileList) {
    super();

    activity = a;
    dataList = fileList;
    layoutId = listRow;
    inflater = (LayoutInflater) activity
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return dataList.size();
}

The modified one is for the above getCountmethod

   @Override
public Object getCount() {
    // TODO Auto-generated method stub
    return numberOfBookRows;
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return dataList.get(position);
}


@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

public void calculateRowsAndColms() {
    totalBooks = 0;
    bookItem = 0;
    numberOfBookRows = 0;
    extraBooks = 0;

    totalBooks = dataList.size();
    bookItem = 3;// TODO: make it dynamic
    if (totalBooks < bookItem && totalBooks > 0) {
        numberOfBookRows = 1;
    } else {
        numberOfBookRows = (totalBooks / bookItem);
        extraBooks = (totalBooks % bookItem);
        if (extraBooks != 0)
            numberOfBookRows++;
    }

    Log.d(TAG, " Total books:" + totalBooks);
    Log.d(TAG, " Number of books to be displayed:" + bookItem);
    Log.d(TAG, " Number of rows occupying the books:" + numberOfBookRows);
    Log.d(TAG, " Number of extra books(odd count):" + extraBooks);
}

This is my View code of arrayadapter

 @Override
public View getView(int position, View convertView, ViewGroup parent) {

    ViewHolder holder;
    View v = convertView;
    Log.d("View", "view" + v);
    calculateRowsAndColms();
    bookImage = R.drawable.book1;
    Log.d("Datalist","size="+dataList.size());
    if (convertView == null) {
        holder = new ViewHolder();
        v = inflater.inflate(layoutId, null, false);

        ImageView image1 = (ImageView) v.findViewById(R.id.image1);
        ImageView image2 = (ImageView) v.findViewById(R.id.image2);
        ImageView image3 = (ImageView) v.findViewById(R.id.image3);

        TextView t1 = (TextView) v.findViewById(R.id.textView1);
        TextView t2 = (TextView) v.findViewById(R.id.textView2);
        TextView t3 = (TextView) v.findViewById(R.id.textView3);

        holder.imgList.add(image1);
        holder.imgList.add(image2);
        holder.imgList.add(image3);

        holder.textList.add(t1);
        holder.textList.add(t2);
        holder.textList.add(t3);

        v.setTag(holder);

    } else {
        holder = (ViewHolder) v.getTag();
    }
    int k;

 if ((position == numberOfBookRows - 1) && extraBooks != 0) {


                    for (int i = 0; i < extraBooks; i++) {
                        Log.d("inside if", "position" + position);
                        Log.d("inside if", "numberofbookrows" + numberOfBookRows);
                        int k = (position * bookItem) + i;
                        holder.imgList.get(i).setBackgroundResource(bookImage);
                        holder.imgList.get(i).setOnClickListener(
                                new OnBookClickListner());
                        holder.imgList.get(i).setVisibility(View.VISIBLE);
                        holder.imgList.get(i).setId(k);
                        holder.textList.get(i).setText(dataList.get(k).get("pdf"));
                        Log.d("if k value","k="+k+"value="+dataList.get(k).get("pdf"));

                    }

                } else if((position <= numberOfBookRows - 1) && totalBooks<bookItem)
                {

                    for (int i = 0; i < totalBooks; i++) {

                        Log.d("inside else", "position" + position);
                        Log.d("inside else", "numberofbookrows" + numberOfBookRows);
                        int k = (position * bookItem) + i;
                        holder.imgList.get(i).setBackgroundResource(bookImage);
                        holder.imgList.get(i).setOnClickListener(
                                new OnBookClickListner());
                        holder.imgList.get(i).setVisibility(View.VISIBLE);
                        holder.imgList.get(i).setId(k);
                        holder.textList.get(i).setText(dataList.get(k).get("pdf"));
                        Log.d("2nd if k value","k="+k+"value="+dataList.get(k).get("pdf"));

                    }
                }
                else 
                {
                    for (int i = 0; i < bookItem; i++) {
                        int k = (position * bookItem) + i;
                        holder.imgList.get(i).setBackgroundResource(bookImage);
                        holder.imgList.get(i).setOnClickListener(
                                new OnBookClickListner());
                        holder.imgList.get(i).setVisibility(View.VISIBLE);
                        holder.imgList.get(i).setId(k);
                        holder.textList.get(i).setText(dataList.get(k).get("pdf"));
                        Log.d("3rd if k value","k="+k+"value="+dataList.get(k).get("pdf"));

                    }

                }

return v;

}

static class ViewHolder {
    ArrayList<ImageView> imgList = new ArrayList<ImageView>();
    ArrayList<TextView> textList = new ArrayList<TextView>();

    // ImageView image1, image2 ,image3;
}

public class OnBookClickListner implements OnClickListener {

    @Override
    public void onClick(View v) {
        Log.d(TAG, " ITEM SELECTED IN LIST VIEW:" + v.getId());
        /*
         * Intent intent = new Intent(MainActivity.this,
         * MainActivity.class); startActivity(intent);
         */
    }

}

}

Now When i run this code , im getting my expected output, but when i try to scroll the list, the app get close and i get fatal exception

    07-22 03:57:26.501: E/AndroidRuntime(1314): FATAL EXCEPTION: main
07-22 03:57:26.501: E/AndroidRuntime(1314): java.lang.IndexOutOfBoundsException: Invalid index 21, size is 20
07-22 03:57:26.501: E/AndroidRuntime(1314):     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at java.util.ArrayList.get(ArrayList.java:308)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at com.example.samplebookshelfdesign.ListViewAdapter.getView(ListViewAdapter.java:151)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.widget.AbsListView.obtainView(AbsListView.java:2161)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.widget.ListView.makeAndAddView(ListView.java:1840)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.widget.ListView.fillDown(ListView.java:675)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.widget.ListView.fillGap(ListView.java:639)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4970)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3126)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.widget.AbsListView.onTouchEvent(AbsListView.java:3400)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.View.dispatchTouchEvent(View.java:7384)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2203)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1938)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2209)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1952)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2209)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1952)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2209)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1952)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2209)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1952)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1966)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1418)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.app.Activity.dispatchTouchEvent(Activity.java:2424)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1914)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.View.dispatchPointerEvent(View.java:7564)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3883)
07-22 03:57:26.501: E/AndroidRuntime(1314):     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3778)

The problem is in your if/else condition. You don't handle the case where position exceeds the number of rows.

if ((position == numberOfBookRows - 1) && extraBooks != 0) {
  // ...
} else {
  // This will also get executed if position > numberOfBooksRows -1
}

You probably should add an additional guard:

if ((position == numberOfBookRows - 1) && extraBooks != 0) {
  // ...
} else if (position < numberOfBookRows - 1) {
  // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM