OiO.lk Blog Android Android Dependency Injection for Work Manager
Android

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



You need to sign in to view this answers

Exit mobile version