Android - CursorAdapter 不工作

标签 android sqlite android-cursoradapter android-cursorloader

我有一个 ChatActivity,它通过 CursorLoader 加载它的数据。 CursorLoader 返回一个带有两个寄存器的游标,但永远不会调用适配器中的 newView 和 bindView 方法。

我的 Activity

public class ChatActivity extends BaseActivity implements LoaderManager.LoaderCallbacks<Cursor> {

    public static final String EXTRA_AMANTEID = "amanteId";

    private EditText messageET;
    private ListView messagesContainer;
    private Button sendBtn;
    private ChatAdapter adapter;
    private Long amanteId;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);

        amanteId = getIntent().getLongExtra(ChatActivity.EXTRA_AMANTEID, 0L);

        messagesContainer = (ListView) findViewById(R.id.messagesContainer);
        messageET = (EditText) findViewById(R.id.messageEdit);
        sendBtn = (Button) findViewById(R.id.chatSendButton);

        RelativeLayout container = (RelativeLayout) findViewById(R.id.container);

        adapter = new ChatAdapter(this);
        getLoaderManager().initLoader(0, null, this);
        messagesContainer.setAdapter(adapter);
    }

    private void scroll() {
        messagesContainer.setSelection(messagesContainer.getCount() - 1);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        return new CursorLoader(ChatActivity.this, MensagemProvider.CONTENT_URI_CONVERSA, null, null, new String[]{Long.toString(amanteId), Long.toString(amanteId)}, null);
    }

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

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

我的适配器

public class ChatAdapter extends CursorAdapter {

    private Cursor cursor;
    private int dataEnvioColumnIndex;
    private int idMensagemColumnIndex;
    private int idRemetenteColumnIndex;
    private int idDestinatarioColumnIndex;
    private int apelidoRemetenteColumnIndex;
    private int apelidoDestinatarioColumnIndex;
    private int textoMensagemColumnIndex;
    private long idColaboradorLogado;

    public ChatAdapter(Context context) {
        super(context, null, false);
    }

    public ChatMessage getItem() {
        ChatMessage message = new ChatMessage();
        SimpleDateFormat dt = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        Date dataEnvio = new Date(cursor.getLong(dataEnvioColumnIndex));
        message.setDate(dt.format(dataEnvio));
        message.setId(cursor.getLong(idMensagemColumnIndex));
        Long de = cursor.getLong(idRemetenteColumnIndex);
        Long logado = BaseApp.getCredentials().getId();
        message.setMe(de.equals(logado));
        message.setMessage(cursor.getString(textoMensagemColumnIndex));
        return message;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View retView = vi.inflate(R.layout.list_item_chat_message, null);
        return retView;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ViewHolder holder = createViewHolder(view);;
        view.setTag(holder);
        ChatMessage chatMessage = getItem();
        boolean myMsg = chatMessage.getIsme() ;//Just a dummy check
        holder.txtMessage.setText(chatMessage.getMessage());
        holder.txtInfo.setText(chatMessage.getDate());
    }

    private ViewHolder createViewHolder(View v) {
        ViewHolder holder = new ViewHolder();
        holder.txtMessage = (TextView) v.findViewById(R.id.txtMessage);
        holder.content = (LinearLayout) v.findViewById(R.id.content);
        holder.contentWithBG = (LinearLayout) v.findViewById(R.id.contentWithBackground);
        holder.txtInfo = (TextView) v.findViewById(R.id.txtInfo);
        return holder;
    }


    private static class ViewHolder {
        public TextView txtMessage;
        public TextView txtInfo;
        public LinearLayout content;
        public LinearLayout contentWithBG;
    }

    @Override
    public Cursor swapCursor(Cursor cursor) {
        if(cursor!=null) {
            cursor.moveToFirst();
            idMensagemColumnIndex = cursor.getColumnIndex(MensagemProvider.COLUMN_MENSAGEMID);
            idRemetenteColumnIndex = cursor.getColumnIndex(MensagemProvider.COLUMN_DE);
            idDestinatarioColumnIndex = cursor.getColumnIndex(MensagemProvider.COLUMN_PARA);
            apelidoRemetenteColumnIndex = cursor.getColumnIndex(MensagemProvider.COLUMN_APELIDO_REMETENTE);
            apelidoDestinatarioColumnIndex = cursor.getColumnIndex(MensagemProvider.COLUMN_APELIDO_DESTINATARIO);
            textoMensagemColumnIndex = cursor.getColumnIndex(MensagemProvider.COLUMN_MENSAGEM);
        }
        notifyDataSetChanged();

        return cursor;
    }
}

我做错了什么?有谁能够帮助我 ? 谢谢!

最佳答案

重写 swapCursor() 是自找麻烦。光标不会定位在适配器期望它定位的位置(在 first 之前)。而且您不调用 super.swapCursor(),因此适配器永远不会真正听到新游标。

我敢打赌,您正在尝试通过每次交换新游标时仅获取一次列索引来“优化”。

首先尝试摆脱 swapCursor() 覆盖并在 getItem() 方法中调用 getColumnIndex()。如果这样可行并且您仍然真的希望每个游标只调用一次 getColumnIndex(),您可以尝试在交换游标时将所有游标索引设置为 -1,然后调用 getColumnIndex() 仅在索引为 -1 时在 getItem() 中。

但不要乱用 swapCursor(),尤其是在不调用 super.swapCursor() 并返回其结果的情况下。

关于Android - CursorAdapter 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32697239/

相关文章:

android - 在 ffmpeg 中读取 JPEG

sql - 如何将该txt文件导入到SqlLiteStudio中的数据库表中

javascript - 通过 Javascript 调用 SQLite 时 Firefox 出错

android - CursorAdapter 并不总是在 AutoCompleteTextView 上工作

android - CursorAdapter 和 FLAG_REGISTER_CONTENT_OBSERVER

android - 光标适配器从下到上加载聊天应用程序列表

java - Retrofit JSON Error 解析错误

android - 我无法在 kotlin webview 中上传图片、视频和文件

android - 我应该在我的应用程序中显式创建 SQLite 表吗?

android - 如何在 TextView 中单击一次获得选择光标