android - 带有返回值(long 或 int)的 Android Room DAO @Insert 如何工作?
问题描述
最近在学习使用DAO。据我了解,所有@Insert
, @Update
, 或@Query
都是异步执行的。并且从纪录片中,@Insert
可以返回一个long
值,它是新rowId
插入的项目(或者List<long>
如果是多个项目)。假设我的 DAO 看起来像这样:
@Insert
long insertTransaction(Transaction transaction);
@Insert
List<Long> insertTransactions(List<Transaction> transactions);
当我在活动或片段中使用这些方法时,是否意味着我在异步任务完成后获得了长值?
<!-- language: lang-none -->
// Do I get 0 if the insert is not complete
// or it will wait till the insert is complete and return long?
long id = viewModel.insertTransaction(transaction)
如果它等待异步任务完成,它不会阻塞主线程(尤其是在插入大列表时)?如果没有,我如何检查插入是否完成?
解决方案
据我了解,所有@Insert、@Update 或@Query 都是异步执行的。
默认情况下,所有@Insert、@Update 或@Query 都是同步执行的。Room 会对此发出警告,如果没有在 RoomDatabase.Builder 中显式使用方法allowMainThreadQueries,您将无法进行同步调用。
当然,不推荐使用同步调用。要使用异步调用,您有几个选项(查看官方文档):
- Kotlin 协程(
suspend
关键字) - RxJava(将返回类型设置为
Single
,Maybe
,Completable
) - 番石榴(将返回类型设置为
ListenableFuture
)。
此外,您可以使用 Threads/ThreadPools 将 DB 操作显式移动到后台线程,并自行管理异步工作(例如,使用回调)。
使用上述选项之一,您将在异步任务结束时收到通知(通知的方法取决于您选择的框架)。否则,您会进行同步调用并阻止 UI 线程。
推荐阅读
- java - WebSocket 握手期间出现 Java 错误的 webSocket:404
- node.js - 将对象放置到 mongoDb 中的根级别
- java - JUnit 和 Mockito 在模拟时返回 null
- sql - postgres 选择由外键链接的所有字符串
- dialogflow-es - 无法将实体中的条目部署到 DialogFlow
- android - 运行 xamarin androd 应用程序后尝试设置 axml 值但不需要访问方法
- c# - 在文本框中阻止任何类型的 URL
- c++ - 使用 if else 将数字转换为单词
- .htaccess - 将 http、https 重定向到 https://www.domain-name
- android - 如何在最近的道路 API 的改造中通过纬度和经度