当前位置: 首页 > 知识库问答 >
问题:

如何使用Room&livedata获取特定的数据字段?

沙靖琪
2023-03-14

我是android和Room Persistence library的新手,我将数据保存在一个名为schoolentry的实体中,它有很多行,其中一个是PrimaryKey cadID(一个int字段)。我需要从用户刚刚输入的最后一个条目中获取cadID。

对于这个问题,我试图使用以下逻辑来获得它:

ViewModelEntry recentEntry = new ViewModelEntry(RegisterActivity.this.getApplication());
int lastCadID = recentEntry.getLastEntry().getValue().getCadID();

但是,当程序到达这一点时,它抛出一个NullPointerException异常

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Integer com.xxxx.xxxx.entities.SchoolEntry.getCadID()' on a null object

这就是我在ViewModel(ViewModelEntry)中实现GetLastEntry():

repository = new ReportRepository(application);
public LiveData<SchoolEntry> getLastEntry() {return repository.getLastEntry(); }

这就是我如何在我的存储库(ReportRepository)中实现GetLastEntry():

ReportDatabase db = ReportDatabase.getDatabase(application);
schoolEntryDao = db.schoolEntryDao();
public LiveData<SchoolEntry> getLastEntry() { return schoolEntryDao.getLastEntry(); }

最后,这是我如何在DAO(SchoolEntryDao)中实现getLastEntry():

    @Query("SELECT * FROM SchoolEntry WHERE cadID = (SELECT MAX(cadID) from SchoolEntry)")
    LiveData<SchoolEntry> getLastEntry();

所以我有两个问题:为什么这个引用指向一个空对象?如果我使用recentry.getLastEntry().getValue(),并且知道getValue会给我一个SchoolEntry对象(我在其中创建了一个getCadID方法来获取该条目的Id),为什么它说它是空的呢?

最重要的是:如何获取这些信息?因为,很明显,我现在做事的方式是行不通的。

谢谢你的帮助!

共有1个答案

淳于飞鸾
2023-03-14

当您调用返回LiveData(即GetLastEntry)的Room Dao函数时,该函数将立即返回LiveData对象,而不一定返回您的内容(即SchoolEntry)。在该函数返回后的一段时间内(通常非常快),Room将用查询结果填充LiveData对象。

为什么这个引用指向一个空对象?

因为您在创建LiveData对象之后立即查询了该对象的值,但您没有给出足够的时间来填充结果。这是返回LiveData的Room方法的预期行为。例如,您可以调用thread.sleep任意几毫秒,结果就会出现。但请不要那样做!有更好的办法来解决这个问题。

如何获取这些信息?

如果希望坚持使用LiveData,则需要观察它并通过使用侦听器获得结果:

LiveData<SchoolEntry> lastEntryLiveData = recentEntry.getLastEntry();

// "this" is used here assuming this class is an Activity, as I inferred from your code above
lastEntryLiveData.observe(this, new Observer<SchoolEntry>() {
    @Override
    public void onChanged(SchoolEntry result) {
        int lastCadID = result.getCadID();

        // you can use lastCadID here, and this method may be called
        // multiple times whenever your database changes and the query
        // "SELECT * FROM SchoolEntry WHERE cadID = (SELECT MAX(cadID) from SchoolEntry)"
        // would return a new result
    }
});

这是异步的,因为所有(或大多数)LiveData访问都应该是异步的。

如果您希望仅同步获取查询的schoolentry结果一次,则需要将Dao方法声明为:

@Query("SELECT * FROM SchoolEntry WHERE cadID = (SELECT MAX(cadID) from SchoolEntry)")
SchoolEntry getLastEntry();

(注意返回类型中缺少livedata)

然后您可以直接调用这个方法,并且它应该同步具有您的结果。但是,该方法不能在主线程上运行,您需要为此创建一个后台线程。这在Kotlin中很容易解决(通过使用协式),而在普通的Java中则要复杂一些。请查看此链接以获得更多信息。

 类似资料:
  • 问题内容: 我正在使用pyodbc在.mbd(访问)文件中对大型数据库进行数据挖掘。 我想创建一个新表,以从几个现有表中获取相关信息(然后将其提供给工具)。 我想我知道我需要传输数据的所有知识,并且我知道如何创建具有列名和数据类型的表,但是 我在获取现有现有各列的数据类型(INTEGER,VARCHAR等)时遇到了麻烦表。 我需要这些类型来兼容地创建新列。 我在互联网(例如this和this)上发

  • 所以我遵循MVVM架构,在那里我有一个银行交易数据库: 我的Dao类有两个查询: 仓库: 视图模型: 在主片段中,我正在用数据库中的所有事务填充回收视图: 我的问题是:如何从DAO调用函数 要填充相同的recyclerView(当按下某个按钮时)?我不能吃这样的东西 在我的DAO中,因为查询应该在另一个线程上执行(我不允许在主线程上执行),所以我的DAO不能返回事务列表<你能提供帮助吗?

  • 因此,我使用LiveData和ViewModel设置获取和插入数据的功能,并使用Room数据库保存数据。 将数据插入数据库后,我的RecyclerView不会更新数据。 RecyclerAdapterTransaksi.kt 使用RecyclerView显示数据库数据的片段 Pemasukkanframent。kt 使用LiveData的ViewModel类 TransaksiViewModel.

  • 一切正常(使用AsyncTask插入、更新、删除),但按id获取一行不是。。。 主要问题是有两种活动。 回收视图 我想在点击RecyclerView列表项后,从数据库中按id获取一个项。如果我用LiveData获取它,我就无法将其与UI线程中的变量同步。 如何从数据库中获取一行? 在DAO中,我有: 在存储库中: 如果我把它写在主线程里 它给出了一个错误: 我应该使用AsyncTask,但如何使用

  • 我有一个从数据库中提取数据的表。在同一张桌子里,我有两个按钮。通过按任意一个按钮,我希望获得所有特定的列数据。我试过几种方法。请参阅下面的代码。 生成上表HTML和PHP: JavaScript:每个警报都是我尝试的不同方法,但没有成功

  • 我有一个创建的sqlite服务器,它保存关于用户的JSON数据。数据看起来像这样: 我也有一个基本的html页面的形式: 我也有使用XMLhttprequest()从服务器获取此数据的代码,但是,该代码只允许获取整个JSON数据并显示所有用户: 我的问题是,如何按用户名搜索用户,因此在HTML表单中,编写Sam Smith,单击按钮后,将只返回第一个用户的信息,而不是数据集中的所有用户?我想在不使