Search code examples
androidandroid-listviewandroid-loadermanagerandroid-cursorloader

Loader doesn't stop adding views to list items when scrolling up and down


I try to load ListView items with a custom CursorLoader into a list. The problem is, if I scroll to the bottom and up again Android adds multiple new images to every list item. My question is, how to prevent Android to load more images into the list.
Column 1 should always have only one image, column 2 two images...

Main.java

public class Main extends FragmentActivity
    implements LoaderManager.LoaderCallbacks<Cursor> {

private Context mCtx       = null;
private MyAdapter mAdapter = null;

private final static String COLUMN_A = "a";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mCtx     = this;
    mAdapter = new MyAdapter(mCtx);

    ((ListView) findViewById(R.id.listview)).setAdapter(mAdapter);
    getSupportLoaderManager().initLoader(0, null, this);
}


@Override
public Loader<Cursor> onCreateLoader(int loader_id, Bundle bundle) {

    return new MyCursorLoader(mCtx) {

        @Override
        public Cursor loadInBackground() {
            MatrixCursor m = new MatrixCursor(new String[]{"_id", COLUMN_A});
            m.addRow(new String[]{"1", "Column 1"});
            m.addRow(new String[]{"2", "Column 2"});
            m.addRow(new String[]{"3", "Column 3"});
            m.addRow(new String[]{"4", "Column 4"});
            m.addRow(new String[]{"5", "Column 5"});
            return m;
        }
    };
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
    mAdapter.changeCursor(c);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    mAdapter.changeCursor(null);
}


private class MyAdapter extends CursorAdapter {
    private final LayoutInflater mInflater;

    public MyAdapter(final Context ctx) {
        super(ctx, null, 0);
        mInflater = LayoutInflater.from(ctx);
    }

    @Override
    public View newView(Context ctx, Cursor c, ViewGroup parent) {
        return mInflater.inflate(R.layout.item, parent, false);
    }

    @Override
    public void bindView(final View v, final Context ctx, final Cursor c) {
        LinearLayout parent = (LinearLayout) v;
        final int position = c.getPosition();

        Log.i("MyAdapter", "Cursor position: "+ position
                + "\tImages: "+ (parent.getChildCount() -1));

        ((TextView) v.findViewById(R.id.content))
            .setText(c.getString(c.getColumnIndex(COLUMN_A)));


        LinearLayout ll = new LinearLayout(ctx);
        ll.setOrientation(LinearLayout.VERTICAL);

        for (int i=0; i<(position+1); i++) {
            SystemClock.sleep(i * 100);
            ImageView img = new ImageView(ctx);
            img.setImageResource(R.drawable.ic_launcher);
            ll.addView(img);
        }

        parent.addView(ll);
    }
}


private abstract class MyCursorLoader extends CursorLoader {

    public MyCursorLoader(Context ctx) {
        super(ctx);
    }

    @Override
    public abstract Cursor loadInBackground();
}

}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".Main" >

    <ListView android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    </ListView>

</RelativeLayout>

item.xml

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

    <TextView android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="30dip"
    android:text="---"
    />


</LinearLayout>


↓ after trying Diogo Bento suggestion on a Galaxy S1: enter image description here


Solution

  • that is not an efficient solution, but you can remove the LinearLayout. an efficient solution is to check if the LinearLayout has the number of childs different to the position and add or remove the images to get the number of images that you want.

    **parent.removeViewAt(1);**
    LinearLayout ll = new LinearLayout(ctx);
    ll.setOrientation(LinearLayout.VERTICAL);
    
     for (int i=0; i<(position+1); i++) {
            SystemClock.sleep(i * 100);
            ImageView img = new ImageView(ctx);
            img.setImageResource(R.drawable.ic_launcher);
            ll.addView(img);
     }
    parent.addView(ll);