I have a problem with trying to use a suggested CursorAdapter implementation together with a CursorLoader. The CursorAdapter works beatifully when I can provide it with a static set of data through a Cursor, but when I try and combine this with a CursorLoader I get a problem with nullpointers. I have pinned it down to the fact that when I feed the adapter a cursor, it is initially empty (set to null as is frequently suggested when dealing with a CursorLoader implementation). The Adapter, on instantiation, loops through the cursor to figure out what state a checkbox is in and then goes through to populate data in various textviews and widgets. Unfortunately, the cursor is null on instantiation, only to be fed sets of data when the CursorLoader is done. I'm trying to figure out if it's at all possible to use this CursorAdapter together with a CursorLoader and would really appreciate some help.
Here's my complete Adapter:
public class ShopperListCursorAdapter extends CursorAdapter implements OnClickListener, LOG {
private LayoutInflater mInflater;
private GroceriesHelper mHelper;
private List<Boolean> mCheckedState;
public ShopperListCursorAdapter(Context context, Cursor cursor, GroceriesHelper helper, int flags) {
super(context, cursor, flags);
mHelper = helper;
mInflater = LayoutInflater.from(context);
for(mCheckedState = new ArrayList<Boolean>(); !cursor.isAfterLast(); cursor.moveToNext()) {
mCheckedState.add(cursor.getInt(cursor.getColumnIndex(Groceries.COLUMN_CHECKED)) != 0);
}
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
Log.d(TAG, "newView");
View view = mInflater.inflate(R.layout.listview_row, null);
ViewHolder holder = new ViewHolder();
holder.amount = (TextView) view.findViewById(R.id.text_amount);
holder.unit = (TextView) view.findViewById(R.id.text_unit);
holder.item = (TextView) view.findViewById(R.id.text_item);
holder.checked = (CheckBox) view.findViewById(R.id.check_item);
holder.checked.setOnClickListener(this);
view.setTag(holder);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
Log.d(TAG, "bindView");
RowData data = new RowData();
data.id = cursor.getInt(cursor.getColumnIndex(Groceries.COLUMN_ID));
data.amount = cursor.getString(cursor.getColumnIndex(Groceries.COLUMN_AMOUNT));
data.unit = String.valueOf(cursor.getInt(cursor.getColumnIndex(Groceries.COLUMN_UNIT_ID)));
data.item = cursor.getString(cursor.getColumnIndex(Groceries.COLUMN_ITEM));
data.position = cursor.getPosition();
ViewHolder holder = (ViewHolder) view.getTag();
holder.amount.setText(data.amount);
holder.unit.setText(data.unit);
holder.item.setText(data.item);
holder.checked.setChecked(mCheckedState.get(data.position));
holder.checked.setTag(data);
}
@Override
public void onClick(View view) {
boolean visibility = ((CheckBox) view).isChecked();
RowData data = (RowData) view.getTag();
Log.d(TAG, "data: " + data.position);
mCheckedState.set(data.position, visibility);
mHelper.setChecked(data.id, visibility == true ? 1 : 0);
}
private static class ViewHolder {
TextView amount;
TextView unit;
TextView item;
CheckBox checked;
}
private static class RowData {
int id;
String amount;
String unit;
String item;
int position;
}
}
Copy and paste
for(mCheckedState = new ArrayList<Boolean>(); !cursor.isAfterLast(); cursor.moveToNext()) {
mCheckedState.add(cursor.getInt(cursor.getColumnIndex(Groceries.COLUMN_CHECKED)) != 0);
}
into a public helper method in your adapter class (i.e. public void populateAdapter()
).
Then, in onLoadFinished
swap the cursor in (with mAdapter.swapCursor(cursor)
) and then call mAdapter.populateAdapter()
. This will ensure that your Cursor
is bound to the adapter before you attempt to populate mCheckedState
.
That said, I'm not entirely sure what you are trying to do with mCheckedState
in the first place... why can't you just check/uncheck the views directly using the Cursor
in bindView
?
The cursor isn't updated even when your database is unless you notify the cursor. What you'll want to do is have a separate structure in your adapter that keeps track of the clicked/non-clicked state and refer to that for the answer. If the answer isn't there, then refer to the cursor (which will be the case the first time you display the list).
来源:https://stackoverflow.com/questions/10785862/custom-cursoradapter-and-checkbox-states