Custom CursorAdapter and CheckBox states

最后都变了- 提交于 2019-12-08 09:16:07

问题


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;
    }
}

回答1:


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?




回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!