Dmitry  Simakov
Dmitry Simakov

Reputation: 710

Android. Could not instantiate Worker

I want to pre-populate my Room database from the json file in the assets folder. I follow the Google Sunflower sample. I copied the SeedDatabaseWorker class:

import android.content.Context
import android.util.Log
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.dmitrysimakov.gymlab.data.GymLabDb
import com.dmitrysimakov.gymlab.data.entity.Training
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import javax.inject.Inject

class SeedDatabaseWorker(val context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
    private val TAG = SeedDatabaseWorker::class.java.simpleName

    @Inject lateinit var database: GymLabDb

    override fun doWork(): Worker.Result {
        val plantType = object : TypeToken<List<Training>>() {}.type
        var jsonReader: JsonReader? = null

        return try {
            val inputStream = context.assets.open("training.json")
            jsonReader = JsonReader(inputStream.reader())
            val plantList: List<Training> = Gson().fromJson(jsonReader, plantType)
            database.trainingDao().insert(plantList)
            Worker.Result.SUCCESS
        } catch (ex: Exception) {
            Log.e(TAG, "Error seeding database", ex)
            Worker.Result.FAILURE
        } finally {
            jsonReader?.close()
        }
    }
}

I'm using Dagger 2, so instead of doing this: Sunflower AppDatabase, I do this:

import android.arch.persistence.db.SupportSQLiteDatabase
import android.arch.persistence.room.Room
import android.arch.persistence.room.RoomDatabase
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.dmitrysimakov.gymlab.GymLabApp
import com.dmitrysimakov.gymlab.data.GymLabDb
import com.dmitrysimakov.gymlab.workers.SeedDatabaseWorker
import dagger.Module
import dagger.Provides
import javax.inject.Singleton

@Module(includes = [ViewModelModule::class])
class AppModule {

    @Singleton
    @Provides
    fun provideDb(app: GymLabApp): GymLabDb {
        return Room
                .databaseBuilder(app, GymLabDb::class.java, "gymlab.db")
                .addCallback(object : RoomDatabase.Callback() {
                    override fun onCreate(db: SupportSQLiteDatabase) {
                        super.onCreate(db)
                        val request = OneTimeWorkRequestBuilder<SeedDatabaseWorker>().build()
                        WorkManager.getInstance().enqueue(request)
                    }
                })
                .fallbackToDestructiveMigration()
                .build()
    }

    @Singleton
    @Provides
    fun provideTrainingDao(db: GymLabDb) = db.trainingDao()
}

But I can't inject the database that has not yet been created. So, how can I access the dao?

Upvotes: 5

Views: 3913

Answers (2)

Dmitry  Simakov
Dmitry Simakov

Reputation: 710

The problem was that I couldn't inject my database into the Worker. I found the solution here: AndroidWorkerInjection

Upvotes: 2

Jeel Vankhede
Jeel Vankhede

Reputation: 12118

Your issue is that SeedDatabaseWorker is still based on Worker() which is deprecated now, so you need to use Worker(Context, WorkerParameters) this constructor.

Check my answer from another post, it'll help you understand WorkManager library.

Edit :

You can now check Worker from that Sunflower demo, it's updated.

Upvotes: 1

Related Questions