Reputation: 143
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);
}
}
Upvotes: 3
Views: 94
Reputation: 16238
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);
}
}
Upvotes: 2
Reputation: 2075
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
Upvotes: 2