带有 sqlite 的 LiveData 不更新 UI

Posted

技术标签:

【中文标题】带有 sqlite 的 LiveData 不更新 UI【英文标题】:LiveData with sqlite not updating UI 【发布时间】:2021-11-15 16:49:43 【问题描述】:

这是从 sqlite 数据库中获取数据作为 livedata 的代码

private LiveData<ArrayList<Message>> loadAllMessagesOfThisChat() 
  final  MutableLiveData<ArrayList<Message>> messages= new MutableLiveData<>();

    ArrayList<Message> messagesArrayList = new ArrayList<>();

    SQLiteDatabase mDb = messagesDbHelper.getReadableDatabase();
    String[] projection = 
            MessageDetails.COLUMN_SENDER_UID,
            MessageDetails.COLUMN_MESSAGE,
            MessageDetails.TIMESTAMP_ID,
            MessageDetails.COLUMN_IMAGE_URI;
    Cursor cursor = mDb.query("receiver" + receiverUID, projection, null, null, null, null, null);
    int messageColumnIndex = cursor.getColumnIndex(MessageDetails.COLUMN_MESSAGE);
    int timestampColumnIndex = cursor.getColumnIndex(MessageDetails.TIMESTAMP_ID);
    int imageURIColumnIndex = cursor.getColumnIndex(MessageDetails.COLUMN_IMAGE_URI);
    int senderUIDColumnIndex = cursor.getColumnIndex(MessageDetails.COLUMN_SENDER_UID);
    while (cursor.moveToNext()) 
        Message message = new Message();
        message.setMessage(cursor.getString(messageColumnIndex));
        message.setImageUrl(cursor.getString(imageURIColumnIndex));
        message.setTimestamp(String.valueOf(cursor.getInt(timestampColumnIndex)));
        message.setUserID(cursor.getString(senderUIDColumnIndex));
        messagesArrayList.add(message);

    
    messages.setValue(messagesArrayList);
    cursor.close();
    mDb.close();

    return (LiveData<ArrayList<Message>>) messages;

我在 oncreate 中使用它

LiveData<ArrayList<Message>> messages=loadAllMessagesOfThisChat();
    messages.observe(this, new Observer<ArrayList<Message>>() 
        @Override
        public void onChanged(ArrayList<Message> messages) 
            messagesAdapter.setMessages(messages);
        
    );

但是每当我发送一条新消息时,它都会被添加到数据库中,但更改不会反映在 UI 中,直到我重新启动我的活动

似乎观察者没有做任何事情

我正在尝试将 livedata 与 sqlite 一起使用,因为由于某些原因我无法使用空间

【问题讨论】:

【参考方案1】:

在您的代码中。没有异步编程,因此您的代码同步运行。 这意味着您首先调用 setValue(),然后返回 liveData 的对象。这导致什么都不做,因为观察者在调用 setValue() 方法后正在设置。所以观察者没有观察到任何东西。

我可以想到 2 个解决方案

    要么进行异步编程,要么在后台线程上获取数据 或者你可以直接返回 ArrayList 的值。在这种情况下,您不必使用 liveData。

【讨论】:

那么我应该在后台线程中调用 loadAllMessagesOfThisChat,然后将观察者附加到它吗? 不,不是方法。您应该添加从 sqlite 获取数据的代码,即从定义“messagesArrayList”对象到关闭数据库,但后台线程中的 setValue() 方法除外,因此它变得异步。我的观点是你应该先返回 liveData 对象,然后在它上面调用 setValue() 方法,然后它应该可以工作。【参考方案2】:

不要在原生 sqllite 中使用 livedata,而是在 更新您的数据库后调用 notifyDataSetChanged()这将使用 最新值重新填充列表视图。

或者,您可以致电reCreate() 重新开始您的活动。

【讨论】:

以上是关于带有 sqlite 的 LiveData 不更新 UI的主要内容,如果未能解决你的问题,请参考以下文章

带有TextWatcher和LiveData的EditText中的光标位置?

对象字段更改的 LiveData 更新

如何观察数据库的变化以更新 LiveData

Android Room LiveData观察器未更新

带有 RxJava Single 的 Android Livedata 在房间数据库中不起作用

抽象 ViewModel 不更新 LiveData Android MVVM