使用WorkManager更新Room数据库条目

7
我是一名可以翻译文本的助手。
我正在尝试在Android中使用WorkManager,因为到目前为止,我一直在使用AsyncTask进行插入更新。我正在尝试在Room数据库中更新用户。我已经在Repository中创建了一个类,在后台处理过程,但我不确定这是否是正确的编码方式。此外,我有点困惑如何在userViewModel中调用方法。
以下是我的代码:
在Repository中:
inner class Test(ctx: Context, params: WorkerParameters) : Worker(ctx, params) {

    override fun doWork(): Result {
        fun updateUser(userId : Int , userName :String , userLastname: String){
            userDao.updateUser(userId, userName, userLastname)
        }
        return Result.success()
    }
}

在viewModel中:
private val workManager: WorkManager = WorkManager.getInstance()
fun updateUser(userID: Int, userName: String, userLastname: String)    {
    workManager.enqueue(OneTimeWorkRequest.from(Repository.Test::class.java))

}

也许这不是使用WorkManager的正确方式,如果有人能帮忙就感激不尽。
2个回答

16

更新以支持协程 worker

您可以只进行轻微更改就可使用您的代码。您可以使用Data类将参数(例如userId、userName等)传递给WorkManager。此外,不需要将Worker类作为内部类,可以将其作为独立类。因此,您的worker类将类似于:

TestWorker.kt

class TestWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {

    override suspend fun doWork(): Result {
        val userId = inputData.getInt("USER_ID")
        val userName = inputData.getString("USER_NAME")
        val userLastname = inputData.getString("USER_LAST_NAME") 
        AppDatabase.getInstance().userDao.updateUser(userId, userName, userLastname)
        return Result.success()
    }
}

TestViewModel.kt

class TestViewModel : ViewModel() {
    fun updateUser(userId: Int, userName: String, userLastName: String) {
        val worker = OneTimeWorkRequest.Builder(TestWorker::class.java)
        val data = Data.Builder()
        //Add parameter in Data class. just like bundle. You can also add Boolean and Number in parameter.
        data.putInt("USER_ID", userId)
        data.putString("USER_NAME", userName)
        data.putString("USER_LAST_NAME", userLastName)
        //Set Input Data
        worker.setInputData(data.build())
        //enque worker
        WorkManager.getInstance().enqueue(worker.build())
    }
}

别忘了像这样将你的数据库设置为单例模式:

@Database(entities = [User::class],
    version = 1,
    exportSchema = false)
abstract class AppDatabase : RoomDatabase() {

    abstract fun userDao(): UserDao

    companion object {

        // For Singleton instantiation
        @Volatile
        private var instance: AppDatabase? = null

        fun getInstance(context: Context): AppDatabase {
            return instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }
        }

        private fun buildDatabase(context: Context) =
            Room.databaseBuilder(context, AppDatabase::class.java, "userdb")
                .build()
    }
}

@SouravKannanthaB 不是必须的。提问者是通过“WorkManager”进行操作的,因此我根据工作管理器的上下文提供了解决方案。我认为他是在将任务推迟到后台线程中使用它。理想情况下,您应该使用“协程”或“RxJava”或任何其他异步框架。 - ankuranurag2
1
如果进程停止,协程不会被暂停吗? - Sourav Kannantha B
1
@Bink 是的,绝对没错。但是这个答案是在2019年1月给出的,当时workmanger还不支持协程。无论如何,我会更新这个答案的。 - ankuranurag2
1
@ankuranurag2,说得对。Stack Overflow 上有很多过时的信息,所以我尽力保持更新,只是我不太舒服随意更改你的相当完整的答案。 - Bink
这不起作用是因为您必须将 doWork 函数设置为 suspend。而且上下文没有传递。 - Marfin. F
显示剩余2条评论

0

如果你遇到了错误make doWork suspend,你可以参考以下答案。

class TestWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {
    val context = ctx
    
    override suspend fun doWork(): Result {
        val userId = inputData.getInt("USER_ID")
        val userName = inputData.getString("USER_NAME")
        val userLastname = inputData.getString("USER_LAST_NAME") 
        AppDatabase.getInstance(context).userDao.updateUser(userId, userName, userLastname)
        return Result.success()
    }
}

详细更改:

Worker 协程Worker

覆盖 suspend fun doWork(): Result


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接