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