androiddependency-injectionandroid-jetpack-composedagger-hilt

Android Dependency Injection for Work Manager


I'm trying to use the Workers to send data and images in the background, for that my worker needs access to a few different repositories.

When I started my project, I followed what I learned on the course in developer.android, so I used manual dependency injection.

I have a AppContainer that links the OfflineRepository with the Repository.

AppContainer.kt

/** Dependency Injection container at the application level */
interface AppContainer {
    val vistoriaRepository: VistoriaRepository
    val ativosRepository: AtivosRepository
}

class DefaultAppContainer(private val context: Context) : AppContainer {
    private val baseUrl = "$dominio/"

    private val json = Json { ignoreUnknownKeys = true }

    private val retrofit: Retrofit = Retrofit.Builder()
        .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
        .baseUrl(baseUrl)
        .build()


    /** Retrofit service object for creating api calls */
    private val retrofitService: AWFApiService by lazy {
        retrofit.create(AWFApiService::class.java)
    }

    /** Dependency Injection - implementação pro VistoriaRepository */
    override val vistoriaRepository: VistoriaRepository by lazy {
        NetworkVistoriaRepository(retrofitService)
    }

    override val ativosRepository: AtivosRepository by lazy {
        OfflineAtivosRepository(VistoriaDatabase.getDatabase(context).ativoDao())
    }
}

And a AppViewModelProvider

AppViewModelProvider.kt


object AppViewModelProvider {
    val Factory = viewModelFactory {

        initializer {
            val application = (this[APPLICATION_KEY] as VistoriaApplication)
            val vistoriaRepository = application.container.vistoriaRepository
            VistoriaViewModel(
                vistoriaRepository = vistoriaRepository,
            )
        }

        initializer {
            AtivosViewModel(
                this.createSavedStateHandle(),
                vistoriaApplication().container.ativosRepository,
                vistoriaApplication().container.imagensRepository,
                vistoriaApplication().container.caracteristicasDoAtivoRepository,
                vistoriaApplication().container.subitensRepository,
                vistoriaApplication().container.imagensDosSubitensRepository
            )
        }
    }
}

//Extension function to queries for [Application] object and returns an instance of [VistoriaApplication].
fun CreationExtras.vistoriaApplication(): VistoriaApplication =
    (this[APPLICATION_KEY] as VistoriaApplication)

The problem is all the content I have found on DI for Worker Manager uses Hilt. So I'm not sure if the problems I'm facing is because I have 2 ways os doing DI.

For the work Manager I did the DI like this.

My Worker

@HiltWorker
class EnviarImagensWorker @AssistedInject constructor (
    @Assisted private val context: Context,
    @Assisted private val workerParams: WorkerParameters,
    private val vistoriaRepository: VistoriaRepository,
    private val ativosRepository: AtivosRepository,
    private val imagensRepository: ImagensRepository,
    private val imagensDosSubitensRepository: ImagensDosSubitensRepository
): CoroutineWorker(context, workerParams){

    override suspend fun doWork(): Result {
       //He does stuff that ne
    }
}

DataModule

@InstallIn(SingletonComponent::class)
@Module
object DataModule {

    @Singleton
    @Provides
    fun provideVistoriaRepository(vistoriaRepository: NetworkVistoriaRepository): VistoriaRepository {
        return vistoriaRepository
    }

    @Singleton
    @Provides
    fun provideAtivosRepository(ativosRepository: OfflineAtivosRepository): AtivosRepository {
        return ativosRepository
    }

    @Singleton
    @Provides
    fun provideImagensRepository(imagensRepository: OfflineImagensRepository): ImagensRepository {
        return imagensRepository
    }

    @Singleton
    @Provides
    fun provideImagensDosSubitensRepository(imagensDosSubitensRepository: OfflineImagensDosSubitensRepository): ImagensDosSubitensRepository {
        return imagensDosSubitensRepository
    }
}

My Application

@HiltAndroidApp
class VistoriaApplication : Application(), Configuration.Provider {
    /** AppContainer instance used by the rest of classes to obtain dependencies */
    lateinit var container: AppContainer
    override fun onCreate() {
        super.onCreate()
        container = DefaultAppContainer(this)
    }


    @Inject
    lateinit var customWorkerFactory: CustomWorkerFactory

    override val workManagerConfiguration =
        Configuration.Builder()
            .setMinimumLoggingLevel(Log.DEBUG)
            .setWorkerFactory(customWorkerFactory)
            .build()

}

class CustomWorkerFactory @Inject constructor(
    private val vistoriaRepository: VistoriaRepository,
    private val ativosRepository: AtivosRepository,
    private val imagensRepository: ImagensRepository,
    private val imagensDosSubitensRepository: OfflineImagensDosSubitensRepository
): WorkerFactory(){
    override fun createWorker(
        appContext: Context,
        workerClassName: String,
        workerParameters: WorkerParameters
    ): ListenableWorker = EnviarImagensWorker(appContext, workerParameters, vistoriaRepository, ativosRepository, imagensRepository, imagensDosSubitensRepository)
}

And one of my repositories

class OfflineAtivosRepository @Inject constructor (private val ativoDao: AtivoDao) : AtivosRepository {
    override fun getAllAtivosStream(): Flow<List<AtivoComImagensCaracteristicasSubitens>> = ativoDao.getAllAtivos()

    override fun getAtivoStream(id: Long): Flow<Ativo?> = ativoDao.getAtivo(id)

}

And the error I'm getting when I try to run the App

The error is really big, and I couldn't find a way to copy and paste the text here.

error image


Solution

  • Missed AWFApiService,AtivoDao,imagemDao,imagemDoSubItemDao in binding. so

    Add AWFApiService

    @Singleton
    @Provides
    fun providesAPIService(retrofit: Retrofit): AWFApiService = retrofit.create(AWFApiService::class.java)
    

    AtivoDao,imagemDao,imagemDoSubItemDao add similar this

    @Singleton
    @Provides
    fun provideAtivoDao(database: Database): AtivoDao = database.AtivoDao()