3

I am so confused. I've found some suggestions on the net but I can't implement it on this code. Here's my problem. Everytime I scroll, list view's order messes up. I have no idea what to do. I really need some help. I will really appreciate your kindness. Here's my code:

public class ListViewAdapterMeasurement extends CursorAdapter {
    TextView lblContent, lblDate;
    DBHelper dbHelper;
    Button btnSelect;

    public ListViewAdapterMeasurement(Context context, Cursor c) {
        super(context, c, FLAG_REGISTER_CONTENT_OBSERVER);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View view = LayoutInflater.from(context).inflate(R.layout.details_feed, parent, false);

        lblContent = (TextView) view.findViewById(R.id.lblContent);
        lblDate = (TextView) view.findViewById(R.id.lblDate);

        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        View convertView = view;
        if (convertView == null)
        {
            LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = vi.inflate(R.layout.details_feed, null);
        }

        dbHelper = new DBHelper(getApplicationContext());

        int intContentIndex = cursor.getColumnIndex((Tables.FeedTable.COLUMN_CONTENT));
        String strContentIndex = cursor.getString(intContentIndex);
        int intDateIndex = cursor.getColumnIndex((Tables.FeedTable.COLUMN_DATE));
        String strDateIndex = cursor.getString(intDateIndex);

        lblContent.setText(strContentIndex);
        lblDate.setText(strDateIndex);


  }
}
  • 2
    your adapter is used for all views! don't use the ui components as member vars but lookup them in bindView method. – Henning Luther Jun 19 '16 at 15:01
  • @HenningLuther does this mean that i should remove the initialization in newView and transfer it to bindView method? – Junmar Calimbas Jose Jun 19 '16 at 15:39
  • 1
    in newView just : return LayoutInflater.from(context).inflate(R.layout.details_feed, parent, false); in bindView : TextView lblContent = (TextView) view.findViewById(R.id.lblContent); TextView lblDate = (TextView) view.findViewById(R.id.lblDate); – Henning Luther Jun 19 '16 at 16:40
  • 1
    @HenningLuther Thankyou so much! Figured it out before your second reply usingyour first advice. Kudos! – Junmar Calimbas Jose Jun 19 '16 at 17:08
  • 1
    Can i give a real answer which you accept then? – Henning Luther Jun 19 '16 at 18:37
  • http://stackoverflow.com/questions/4567969/viewholder-pattern-correctly-implemented-in-custom-cursoradapter take a look at this question – misman Jun 19 '16 at 19:08

2 Answers2

2

In Android the views can be used several times, which means an already instantiated view from "newView" can be used in "bindView" more than once.To be clear: "newView" is called not so often(<=) than "bindView". Saving states in "newView" therefor is not a thing you can do. In "newView" you can only manipulate properties which counts for all views ever instantiated from this adapter which are not manipulated in "bindView". All dynamic values for each single row( or item) has do be set in "bindView" since there a reused view can(and will) appear. Saving single inner views of the row (or item) in your adapter leads to unexpected behavior and can not be done. This is your problem. "newView" is called when there is no already instantiated and free(not shown/ recyclable) view in the "view-object-pool". Also you must consider to reset certain subviews in "bindView" in the case an already filled view comes along here and a property stays unset for certain row/item in special circumstances. At the end: You can not know if in "bindView" the given view is a newly constructed or recycled one. Hope that clear things. Happy coding

Henning Luther
  • 2,067
  • 15
  • 22
2

The main issue with your code is that lblContent and lblDate are members of the adapter and get overriden any time newView() is called. Instead, you should store pair of these variables for each View which gets instantiated in newView(), and use them in bindView().

In order to achieve this, you can use the so-called ViewHolder pattern. A general idea behind this pattern can be seen in the below code (which is based on your original code, but I didn't test it):

public class ListViewAdapterMeasurement extends CursorAdapter {

    /**
     * One instance of this class will be attached to each View in order to prevent 
     * repeated calls to findViewById()
     */
    private static class ViewHolder {
        private TextView lblContent;
        private TextView lblDate;

        public ViewHolder(TextView content, TextView date) {
            lblContent = content;
            lblDate = date;
        }

    }


    DBHelper dbHelper;

    public ListViewAdapterMeasurement(Context context, Cursor c) {
        super(context, c, FLAG_REGISTER_CONTENT_OBSERVER);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View view = LayoutInflater.from(context).inflate(R.layout.details_feed, parent, false);

        TextView lblContent = (TextView) view.findViewById(R.id.lblContent);
        TextView lblDate = (TextView) view.findViewById(R.id.lblDate);

        ViewHolder viewHolder = new ViewHolder(lblContent, lblDate); // put references to sub-Views into ViewHolder

        view.setTag(viewHolder); // attach ViewHolder to each newly created View

        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        dbHelper = new DBHelper(getApplicationContext());

        int intContentIndex = cursor.getColumnIndex((Tables.FeedTable.COLUMN_CONTENT));
        String strContentIndex = cursor.getString(intContentIndex);
        int intDateIndex = cursor.getColumnIndex((Tables.FeedTable.COLUMN_DATE));
        String strDateIndex = cursor.getString(intDateIndex);

        ViewHolder viewHolder = (ViewHolder) view.getTag(); // retrieve View's ViewHolder

        viewHolder.lblContent.setText(strContentIndex);
        viewHolder.lblDate.setText(strDateIndex);
  }

}
Vasiliy
  • 16,221
  • 11
  • 71
  • 127