【问题标题】:LiveData returning zero instead of correct integerLiveData 返回零而不是正确的整数
【发布时间】:2021-04-30 20:52:12
【问题描述】:

我正在使用 Room 和 LiveData 在我的应用程序中管理我的 SQLite 数据库。我需要从表中获取一个数据字段,即主键,自动生成的字段。为此,我在我的活动类中编写以下代码:

//Method to insert the new entry in the database
 ViewModelEntry.insert(newEntry);
 ViewModelEntry recentEntry = new ViewModelEntry(RegisterActivity.this.getApplication());

//Observing the LiveData to get the last entry cadID
 recentEntry.getLastEntry().observe(this, lastEntry -> lastCadID = lastEntry.getCadID());
 Toast.makeText(this, "lastCadID = " + lastCadID, Toast.LENGTH_LONG).show();
//This should return the last ID inserted (7, for exemple) but is returning 0 instead

 Intent itemInspectionIntent = new Intent(RegisterActivity.this, InspectionActivity.class);
 itemInspectionIntent.putExtra(MEMORIAL_ITEM_ENTRY, lastCadID);
 startActivity(itemInspectionIntent);

其中ViewModelEntry是我对ViewModel类的实现,insert是通过@insert Room方法将<NewEntry>对象插入数据库的实现。

编辑:这是<insert>方法的实现>

//ViewModel implementation

//Presented in a code snippet below:
//public static ReportRepository repository;
 public static void insert(SchoolEntry schoolEntry) { repository.insertSchoolEntry(schoolEntry); }

//Repository implementation
public void insertSchoolEntry(SchoolEntry schoolEntry) {
        ReportDatabase.dbWriteExecutor.execute(() -> schoolEntryDao.insertEntry(schoolEntry));
    }

//DAO Implementation
    @Insert()
    void insertEntry(SchoolEntry schoolEntry);

这是<dbWriteExecutor> 的实现,它出现在我的<insertSchoolEntry> 方法的Repository 实现中:(这个是在我的Database 类中实现的):

public static final ExecutorService dbWriteExecutor = Executors.newFixedThreadPool(NUMBER_THREADS);
//NUMBER_THREADS = 4

编辑结束

当我尝试获取刚刚插入的条目的<cadID> 字段的值时,就会出现问题。出于某种原因,此代码返回 0 而不是最后一个条目的值。

这些是我的 ViewModel、Repository 和 DAO 中 <getLastEntry> 方法的实现:

//ViewModel implementation
public static ReportRepository repository;

public ViewModelEntry(@NonNull Application application) {
        super(application);
        repository = new ReportRepository(application); }

 public LiveData<SchoolEntry> getLastEntry() {return repository.getLastSchoolEntry(); }


//Repository Implementation
private SchoolEntryDao schoolEntryDao;

public ReportRepository(Application application) {
        ReportDatabase db = ReportDatabase.getDatabase(application);
        schoolEntryDao = db.schoolEntryDao(); }

public LiveData<SchoolEntry> getLastSchoolEntry() { return schoolEntryDao.getLastEntry(); }


//DAO Implementation

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

插入过程完美无缺,因为我使用数据库检查器检查条目是否已插入。此外,当我在数据库检查器中运行该 SQLite 查询时,它确实给了我刚刚记录在我的数据库中的条目。有人可以帮我解决这种情况吗?

【问题讨论】:

  • 能否分享一下ViewModelEntry.insert()函数的实现。另外,你的第一个代码 sn-p 是在主线程上运行的吗?
  • @NavjotSinghBedi 我已经用您要求的实现更新了我的问题。关于sn-p,我想它是在主线程中运行的。我仍然对如何在我的应用程序中实现多个线程有一些疑问,但是,由于在尝试从主线程访问数据库时出错之前,我几乎可以肯定它正在运行。

标签: java android sqlite android-room


【解决方案1】:

发生了什么?

插入发生在后台线程中,我们不等待插入完成。这会导致在插入之前提取最后一个cadId,从而导致值为 0。

建议的解决方案

  1. 进入后台线程
  2. 执行插入ViewModelEntry.insert(newEntry); 并等待它完成。
  3. 获取最后插入的项目"SELECT * FROM SchoolEntry WHERE cadID == (SELECT MAX(cadID) from SchoolEntry)"。将 Dao LiveData 连接到recentEntry,这已经在主线程上观察到了。

【讨论】:

  • 我怎样才能做到这一点?线程.sleep?不过,我读过这不是一个好习惯。
  • 您可以通过 Kotlin Coroutine 或 RxJava 实现这一点。它们是 Android 中线程的一个很好的组件。
  • 您能给我举个例子,说明在这种情况下如何正确使用 Completable 吗?我正在尝试,但我认为我没有正确使用它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多