我尝试将数据从 Worker 保存到 Room 数据库。
版本:
- 工作运行时 Ktx - android.arch.work:work-runtime-ktx:1.0.0-alpha02
- 房间 - android.arch.persistence.room:runtime:1.1.0 和 android.arch.persistence.room:compiler:1.1.0
MainActivity.kt
private fun runDataDownloadWork() {
WorkManager.getInstance()
.beginWith(dwElementTypesWork)
.then(dwElementsWork)
.enqueue()
WorkManager.getInstance().getStatusById(dwElementsWork!!.id)
.observe(this, Observer { workStatus ->
if (workStatus != null && workStatus.state.isFinished) {
Log.d("WorkManager", "dwElementsWork finished")
}
})
}
private fun createWorkRequests() {
dwElementsWork = OneTimeWorkRequestBuilder<DWElementsWork>()
.addTag(DWElementsWork.TAG)
.setConstraints(wifiConstraints)
.build()
dwElementTypesWork = OneTimeWorkRequestBuilder<DWElementTypesWork>()
.addTag(DWElementTypesWork.TAG)
.setConstraints(wifiConstraints)
.build()
}
DWElementsWork.kt
class DWElementsWork : Worker() {
companion object {
const val TAG = "dw_elements_work"
}
override fun doWork(): WorkerResult {
val apiService: APIService = ServiceGenerator
.createService(applicationContext, MyAPIService::class.java)
var elementDao: ElementDao? = AppDatabase
.getInstance(context = applicationContext)
.elementDao()
val response = apiService.getElements().execute()
if (response.isSuccessful) {
val elements = response.body()
try {
elementDao?.insertElements(elements!!)
} catch (e: Exception) {
e.printStackTrace()
} finally {
return WorkerResult.SUCCESS
}
}
Log.e("BACKGROUND_WORKER", response.errorBody()?.string())
return WorkerResult.FAILURE
}
}
应用数据库.kt
@Database(entities = [
(Element::class)
], version = 9, exportSchema = false)
abstract class AppDatabase: RoomDatabase() {
abstract fun elementDao(): ElementDao
companion object {
private var sInstance: AppDatabase? = null
/**
* Gets the singleton instance of AppDatabase.
*
* @param context The context.
* @return The singleton instance of AppDatabase.
*/
@Synchronized
fun getInstance(context: Context): AppDatabase {
if (sInstance == null) {
sInstance = Room
.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"my_database.db"
)
.fallbackToDestructiveMigration()
.build()
}
return sInstance!!
}
}
}
主要问题在于尝试调用elementDao?.insertElements(elements!!)
它时会出现以下错误:
堆栈跟踪
06-20 15:57:09.660 25193-25226/com.myapp.app E/ROOM: Cannot run invalidation tracker. Is the db closed?
java.lang.IllegalStateException: The database '/data/user/0/com.myapp.app/databases/my_database.db' is not open.
at android.database.sqlite.SQLiteDatabase.throwIfNotOpenLocked(SQLiteDatabase.java:2287)
at android.database.sqlite.SQLiteDatabase.createSession(SQLiteDatabase.java:409)
at android.database.sqlite.-$$Lambda$RBWjWVyGrOTsQrLCYzJ_G8Uk25Q.get(Unknown Source:2)
at java.lang.ThreadLocal$SuppliedThreadLocal.initialValue(ThreadLocal.java:284)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180)
at java.lang.ThreadLocal.get(ThreadLocal.java:170)
at android.database.sqlite.SQLiteDatabase.getThreadSession(SQLiteDatabase.java:403)
at android.database.sqlite.SQLiteProgram.getSession(SQLiteProgram.java:101)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
at android.arch.persistence.db.framework.FrameworkSQLiteStatement.executeUpdateDelete(FrameworkSQLiteStatement.java:45)
at android.arch.persistence.room.InvalidationTracker$1.run(InvalidationTracker.java:321)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
我在插入元素之前停止了调试器并AppDatabase.getInstance(applicationContext).isOpen
返回false。
难道我做错了什么?
是否可以将数据从工人保存到房间?
也许applicationContext (getApplicationContext()) 没有提供适当的上下文并且 AppDatabase 实例化很糟糕?
提前致谢!