Search code examples
androidlistviewsplitandroid-inflate

First item of listview shows repeated results


My app has a dialog that shows a listview of favorite balls an user has saved. Each item of the listview should have 6 balls.

Code:

String action = "favoriteId ASC"; 
        Favorite = Select.from(Favorites.class).where(Condition.prop("favoritemode").eq(""+ Constants.mode)).orderBy(action).list();
        FavAdapter adapter = new FavAdapter(LuckyNumber.this, Favorite);
        lv_content.setAdapter(adapter);


public class FavAdapter extends ArrayAdapter<Favorites> {
        public FavAdapter(Context context, List<Favorites> fav) {
            super(context, 0, fav);
        }

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

            Favorites fav = getItem(position);
            if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_favorite, parent, false);
            }


            final LinearLayout ll_ball2 = (LinearLayout) convertView.findViewById(R.id.ll_ball2);
            ImageView btn_use = (ImageView) convertView.findViewById(R.id.btn_use);
            ImageView btn_delete = (ImageView) convertView.findViewById(R.id.btn_delete);
            TextView tv_check = (TextView) convertView.findViewById(R.id.tv_check);             

            String result = fav.getfavoriteslot();

            String [] temp = null;
            temp = result.split("--");

            String ss = "";
            for (int m=0; m< temp.length; m++)
            {
                try
                {
                    ss = ss + "." + temp[m] ;
                    ImageView slot_ball = new ImageView(LuckyNumber.this);
                    slot_ball.setEnabled(false);
                    slot_ball.setImageBitmap(return_bm (Integer.valueOf(temp[m])+""));
                    slot_ball.setScaleType(ImageView.ScaleType.FIT_XY);
                    ll_ball2.addView(slot_ball);
                }
                catch (Exception ex)
                {

                }
            }
            tv_check.setText(""+ss + "...Size=" + temp.length + "Childview=" + ll_ball2.getChildCount());

            return convertView;
        }
    }

list_item_favorite.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@null"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/ll_row2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="left|center_vertical"
        android:orientation="horizontal" >

        <RelativeLayout
            android:id="@+id/keyboard_frame_btn_row"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:orientation="horizontal"
            android:splitMotionEvents="false" >

            <LinearLayout
                android:id="@+id/ll_ball2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:layout_gravity="left|center_vertical"
                android:gravity="left|center_vertical"
                android:splitMotionEvents="false">
            </LinearLayout>

            <TextView
                android:id="@+id/tv_check"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/ll_ball2">

            </TextView>

            <ImageButton
                android:id="@+id/btn_use"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_margin="@dimen/dp2"
                android:layout_toLeftOf="@+id/btn_delete"
                android:background="@null"
                android:scaleType="fitCenter"
                android:src="@drawable/btn_use_selector" />

            <ImageButton
                android:id="@+id/btn_delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_gravity="center_vertical"
                android:layout_margin="@dimen/dp2"
                android:background="@null"
                android:scaleType="fitCenter"
                android:src="@drawable/btn_delete_selector" />

        </RelativeLayout>
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/row3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp2"
        android:gravity="center"
        android:splitMotionEvents="false" >

        <View
            android:id="@+id/view1"
            android:layout_width="fill_parent"
            android:layout_height="2px"
            android:layout_margin="@dimen/dp5"
            android:background="@color/black" />
    </RelativeLayout>

</LinearLayout>

Question:

tv_check shows that for each favorite slots, indeed it knows each slot has 6 balls (size =6). It appears that it is the listview problem inflating wrongly to the first item. The first row of listview shows many repeated items, while the balls starting from the second row are in order. Each row should have 6 balls. The getChildCount shows a pattern as follows:

For 3 slots saved, childcount of first row is 150 (=6balls*3slots*8 + 6).

For 4 slots saved, childcount of first row is 198 (=6balls*4slots*8 + 6).

For 5 slots saved (as in screen capture below), childcount of first row is 246 (=6balls*5slots*8 + 6).

The screen capture is as follows: enter image description here


Solution

  • It seems that getView() in general - and especially getView(0) - will be called more often than there are items in the data list. This is not a bug of ListView or ArrayAdapter, it's simply the way things are.

    In your implementation of getView(), you only add child Views to the LinearLayout, you never remove them.

    So if a row is recycled, the number of child Views will become too large. This will happen not only for the first row but also when you scroll up and down (if the list is long enough) and so cause more rows to be recycled.

    Since each row should have six balls, you can add the six ImageViews to each LinearLayout right after the row has been inflated (or even make them part of the layout xml file) and later on loop through the ImageViews to exchange the Bitmap depending on the data for the current position.