从androidx.work.Worker将数据保存到Room失败

时间:2018-06-20 14:27:10

标签: android kotlin android-room android-workmanager

我尝试将数据从“工作者”保存到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
    }
}

AppDatabase.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!!)时存在主要问题,它会产生以下错误:

StackTrace

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实例化不好?

谢谢!

0 个答案:

没有答案