Search code examples
androidandroid-listviewandroid-cursoradapterandroid-cursorloader

Editing list view items dynamically when using cursor adapters and loaders


I'm writing a tiny messaging app and I've recently encountered this problem.

I've got a ListFragment subclass, which implements a CursorLoader callback. The built-in ListView is bound to a SimpleCursorAdapter. Every row view in this list has a level drawable as a background. I'd like to switch between the levels depending on the database info (whether the message was sent or not).

My question is how do you change the background of a single row in this case? Do I have to access it through the adapter? I'm pretty sure this should be done in the onLoadFinished method. But this code gives me NullPointerException. If you could point me in the right direction, I would be really grateful.

public class MessagesFragment extends ListFragment implements 
                              LoaderManager.LoaderCallbacks<Cursor>{

private static MessagesFragment fragment;
private static MainActivity activity;
private static SimpleCursorAdapter adapter;

public static MessagesFragment getInstance() {
    if (fragment == null)
        fragment = new MessagesFragment();

    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    activity = (MainActivity) getActivity();

    adapter = new SimpleCursorAdapter(activity, R.layout.list_item, null,
            new String[] {DataProvider.KEY_NUMBER, DataProvider.KEY_MESSAGE, DataProvider.KEY_TIME},
            new int [] {R.id.item_field_number, R.id.item_field_message, R.id.item_field_time}, 0);
    setListAdapter(adapter);

    getLoaderManager().initLoader(0, null, this);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_messages, null);
}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);

    activity.showDetails(Long.valueOf(id).intValue());
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(activity, DataProvider.CONTENT_URI, null, null, null, null);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    adapter.swapCursor(data);

    while (data.moveToNext()) {
        int id = data.getInt(data.getColumnIndex(DataProvider.KEY_ID));
        int sent = data.getInt(data.getColumnIndex(DataProvider.KEY_SENT));

        this.getListView().getChildAt(id).getBackground().setLevel(sent);
    }
}

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

}


Solution

  • This should Help!

    public class SampleAdapter extends SimpleCursorAdapter {
    
        private LayoutInflater inflater;
        private Cursor cursor;
        private Context context;
    
        public SampleAdapter(Context context, int layout, Cursor c, String[] from, int[]            to, int flags) {
            super(context, layout, c, from, to, flags);
            this.context = context;
            cursor = c;
            inflater = LayoutInflater.from(context);
        }
    
        @Override
        public int getCount() {
            return cursor == null ? 0 : cursor.getCount();
        }
    
        @Override
        public Object getItem(int position) {
           return null;
        }
    
        @Override
        public long getItemId(int position) {
            return 0;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
    
            if (cursor != null) {
                ViewHolder holder;
                cursor.moveToPosition(position);
    
                if (convertView == null) {
                    convertView = inflater.inflate(R.layout.list_item, parent, false);
                    holder = new ViewHolder(convertView);
                    convertView.setTag(holder);
                } else {
                    holder = (ViewHolder) convertView.getTag();
                }
                convertView.getBackground().setLevel(cursor.getInt(cursor.getColumnIndex(DataProvider.KEY_SENT)));
                holder.number.setText(cursor.getString(cursor.getColumnIndex(DataProvider.KEY_NUMBER)));
                holder.message.setText(cursor.getColumnIndex(DataProvider.KEY_MESSAGE)));
                holder.time.setText(cursor.getColumnIndex(DataProvider.KEY_TIME)));
            }
    
            return convertView;
        }
    
        @Override
        public Cursor swapCursor(Cursor c) {
            cursor = c;
            return super.swapCursor(c);
        }
    
        private class ViewHolder {
    
            TextView number;
            TextView message;
            TextView time;
    
            public ViewHolder(View view) {
                number = (TextView) view.findViewById(R.id.item_field_number);
                message = (TextView) view.findViewById(R.id.item_field_message);
                time = (TextView) view.findViewById(R.id.item_countries_time);
            }
        }
    }