【问题标题】:Fetch recently inserted row id using Room library使用 Room 库获取最近插入的行 ID
【发布时间】:2020-09-12 06:43:54
【问题描述】:

我正在使用房间持久性库来更新数据库。我被困在想要获取最近插入记录的 id 的地方。

我知道使用 long as 作为 insert 方法的返回类型会返回 id。但是我通过视图模型访问这个 Dao 方法。

我的DAO方法如下:

//MyDao
@Insert
long insert(RecordItem record);

通过执行以下操作从存储库访问此方法:

//MyRepository
public class MyRepository {
    private MyDao myDao;

    public MyRepository(@NonNull Application application) {
        MainDatabase mainDatabase = MainDatabase.getInstance(application);
        myDao = mainDatabase.myDao();
    }

    public void insert(RecordItem record) {
        MainDatabase.dbWriteExecutor.execute(() -> {
            myDao.insert(record);
        });
    }
}

并且从viewmodel调用repository方法如下:

//MyViewModel
public void insert(RecordItem record) {
    repository.insert(record);
}

最后viewmodel方法为:

//MyActivity
myViewModel.insert(record);

我的问题是,我不知道如何通过 viewmodel 方法获得长时间返回。我尝试在存储库中这样做

//MyRepository
public class MyRepository {
    private MyDao myDao;
    private long id;

    public MyRepository(@NonNull Application application) {
        MainDatabase mainDatabase = MainDatabase.getInstance(application);
        myDao = mainDatabase.myDao();
    }

    public long insert(RecordItem record) {
        MainDatabase.dbWriteExecutor.execute(() -> {
            id = myDao.insert(record);
        });
        return id;
    }
}

以及随后对 viewmodel 方法的更改。

但是,它返回 0,我想这是因为 insert 方法在不同的线程上执行,并且在到达语句后立即返回 id(如果我错了,请纠正我)。

提前致谢。

【问题讨论】:

  • 您可以使用回调接口的方式进行尝试。将单个方法接口作为方法参数传递给存储库方法插入,并在执行方法上调用它以提供回调。
  • @JeelVankhede 你能解释一下如何按照你的建议做吗?
  • this answer 中给出了使用Callable 执行后台工作并返回结果的示例。

标签: java android android-sqlite android-room


【解决方案1】:

您可以针对您的问题采用以下解决方案:

创建回调接口如下:

public interface DbInsertCallback {
    void onInsert(long insertedItemId);
}

然后在您的存储库上使用此接口insert(RecordItem record) 方法,如下用法:

public class MyRepository {
    
    // ... Some repo code ...

    public void insert(RecordItem record, DbInsertCallback callback) {
        MainDatabase.dbWriteExecutor.execute(() -> {
            long id = myDao.insert(record);
            callback.onInsert(id);
        });
    }

    // ... Rest of repo code ...
}

并且还对调用者站点进行必要的更改(即 ViewModel 和 Activity) 以提供此回调类的对象作为参数。要实现此接口,您可以创建该接口的对象以及实现,或者像提供 this 一样在上下文中传递它。

【讨论】:

  • Dao中的Insert返回一个long,而你展示的DbInsertCalback接口使用的是long。那么在 MyRepository 中,“int id = myDao.insert(record)”不应该也设置为 long 吗?那么“long id = myDao.insert(record);”?
  • @AJW 这很好,感谢您的提醒。我已经编辑了答案。那里漏掉了错字。同样在将来,如果您有此权限,我建议您在任何帖子上编辑答案,否则您也可以请求更改。
【解决方案2】:

你也可以使用 RxJava 来解决这个问题,insert 方法会返回Single<Long>

@Insert
Single<long> insert(RecordItem item)

然后在调用 insert 时调用 subscribe 以获取返回的 id 或使用 flatMap 使用 RxJava 进行任何进一步的操作。

myDao.insert(record).subscribeWith(new DisposableSingleObserver<long>() {

    @Override
    public void onSuccess(long id) {
        // handle the id
    }

    @Override
    public void onError(Throwable e) {
        // handle the error case
    }
}

我建议您进一步了解 RxJava,因为它使异步编程更加自然且易于使用,而且 Room 也开箱即用地实现了它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多