使用游标适配器和加载器动态编辑列表视图项

3
我正在编写一个小型消息应用程序,最近遇到了这个问题。
我有一个ListFragment子类,它实现了CursorLoader回调。内置的ListView绑定到SimpleCursorAdapter。此列表中的每个行视图都有级别可绘制的背景。根据数据库信息(消息是否已发送),我想在级别之间切换。
我的问题是如何更改单个行的背景?我必须通过适配器访问它吗?我非常确定应该在onLoadFinished方法中完成此操作。但是,这段代码给我NullPointerException。如果您能指点我正确的方向,我将不胜感激。
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);
}

}


谢谢!现在我的帖子看起来好多了。真希望我能给你的编辑点赞 :) - Nikolai
空指针异常发生在哪里? - RoraΖ
LogCat指向这一行代码: this.getListView().getChildAt(id).getBackground().setLevel(sent);这些值不是空的。我已经检查过了。 - Nikolai
哪些值不为空?我会将该行代码拆分成单独的几行以进行调试,并打印每个函数的返回值。如果idsent不为null,则在while循环执行期间,其中一个函数返回了null。我认为是getChildAt(id)的问题。 - RoraΖ
尝试并实现自己的SimpleCursorAdapter。这只需要2分钟,而且你可以更加清晰、轻松地完成你想要的事情。 - SemaphoreMetaphor
显示剩余3条评论
2个回答

2

这应该有所帮助!

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

再次感谢!我听说ViewHolder更有效率,也许我应该使用它。一旦我拥有足够的声望,我会点赞你的帖子 ;) - Nikolai

0
原來我應該使用SimpleCursorAdapter而不是使用回調方法來實現。非常感謝@bbaker的指導:) 如果有人感興趣,這裡是代碼:
private class CustomAdapter extends SimpleCursorAdapter {

    private LayoutInflater inflater;
    private int layout;

    public CustomAdapter(Context context, int layout, Cursor cursor,
            String[] from, int[] to, int flags) {
        super(context, layout, cursor, from, to, flags);
        inflater = LayoutInflater.from(context);
        this.layout = layout;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return inflater.inflate(layout, null);
    }

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

        if (cursor != null && cursor.getCount() > 0) {
            TextView timeView = (TextView) view.findViewById(R.id.item_field_time);
            int sent = cursor.getInt(cursor.getColumnIndex(DataProvider.KEY_SENT));
            timeView.getBackground().setLevel(sent);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接