Search code examples
androidkotlinandroid-roomandroid-jetpackandroid-workmanager

Update database entry in Room using WorkManager


I am trying to use WorkManager in Android because till now I have done my insert updates using AsyncTask. I'm trying to update user in Room database. I have created a class in Repository to do the process in background but I don't know if this is the right way to code. Also I am a bit confused how to call the method in userViewModel.

Here is my code:

In 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()
    }
}

And in viewModel:

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

}

Maybe this is not the right way to use WorkManager so I would appreciate it if anyone can help me.


Solution

  • Updated to support Coroutine Worker

    You can use your code with minor changes. You can pass your parameters like userId, userName etc to WorkManager using Data class. Also there is no need to make the Worker class an inner class. Just make it an independent class.So basically, you worker class would look something like:

    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())
        }
    }
    

    Don't forget to make your database singleton like this:

    @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()
        }
    }