Utilizando WorkManager com Hilt - Injeção de dependência na classe Worker
Hillan Vieira
Posted on July 8, 2021
WorkManager
WorkManager é uma API para programação de tarefas assíncronas que nos permite programar tarefas para serem executadas mesmo quando o app é fechado.
Hilt
Hilt é uma biblioteca de injeção de dependências para android criada com base na biblioteca Dagger.
Nesse artigo eu vou demonstrar como utilizar injeção de dependências na classe Worker da API WorkManager com Hilt
Adicionando as dependências do WorkManager
build.gradle(Module)
dependencies {
implementation "androidx.work:work-runtime-ktx:2.5.0"
androidTestImplementation "androidx.work:work-testing:2.5.0"
testImplementation "androidx.work:work-testing:2.5.0"
}
Definindo um trabalho usando a classe Worker sem utilizar injeção de dependência.
class SomeWork(appContext: Context, workerParams: WorkerParameters):
Worker(appContext, workerParams) {
override fun doWork(): Result {
val user: User = User("John Doe", 32)
print(user.toString())
return Result.success()
}
}
No exemplo acima a classe SomeWork
que estende Worker
instancia um objeto do tipo User e imprime o resultado no terminal. Nos exemplos a seguir veremos como passar User via parâmetro com hilt
Criar uma WorkRequest e enviar para o sistema
//Criando request
val doSomeWorkRequest: WorkRequest =
PeriodicWorkRequestBuilder<SomeWork>(15,TimeUnit.Minutes)
.build()
//Enviando para o sistema
WorkManager.getInstance(context)
.enqueueUniquePeriodicWork(
"AppNameSomeWork",
ExistingPeriodicWorkPolicy.KEEP,
doSomeWorkRequest
)
No exemplo acima foi criada uma requisição que irá se repetir a cada 15 minutos que é o tempo mínimo permitido pelo sistema. A cada 15 minutos será executada a linha de código print(user.toString())
dentro no método doWork()
na classe SomeWork
Adicionando Hilt no projeto
build.gradle(Project)
buildscript {
//...
dependencies {
//...
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.37'
}
}
build.gradle(Module)
//...
plugins {
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
android {
//...
//O Hilt usa recursos do Java 8, ativar o Java 8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
//...
annotationProcessorOptions {
//O importante aqui é substituir = por += caso seu
//projeto não esteja assim
arguments += [... ]
}
}
}
kapt {
correctErrorTypes true
}
dependencies {
//Dagger - Hilt
implementation 'com.google.dagger:hilt-android:2.37'
kapt 'com.google.dagger:hilt-compiler:2.37'
kapt 'androidx.hilt:hilt-compiler:1.0.0'
implementation 'androidx.hilt:hilt-work:1.0.0'
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0-alpha03'
}
Adicione as dependências e verifique as configurações.
Anotando a class do projeto que estende Application()
AppNameApplication.kt
@HiltAndroidApp
class AppNameApplication : Application() {
override fun onCreate() {
super.onCreate()
//...
}
}
Essas anotações preparam as classes para receber a injeção de dependência pelo Hilt.
O hilt também é compatível com as seguintes classes:
Activity, Fragment, View, Service e BroadcastReceiver.
.Injetar dependências via hilt numa classe que não é compatível demanda um trabalho a mais.. talvez um próximo artigo. Mas o nosso foco aqui é a classe Worker
então vamos lá.
Criando um modulo do Hilt
AppModule.kt
@InstallIn(SingletonComponent::class)
@Module
object AppModule {
@Singleton
@Provides
fun provideUser(): User{
return User("John Doe", 32)
}
}
Agora podemos injetar a instancia de User. Reparem nas anotações elas são importantes para entender os detalhes consultem a documentação do Hilt
hilt-android
Preparando a classe SomeWork
para receber a injeção de dependência.
@HiltWorker
class SomeWork @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
val user: User):
Worker(appContext, workerParams) {
override fun doWork(): Result {
print(user.toString())
return Result.success()
}
}
Agora já estamos usando a instancia de User que vem via injeção do Hilt na classe SomeWork
mas ainda precisamos fazer mais algumas coisas para tudo funcionar. O sistema cria uma instancia de WorkManager
com uma configuração padrão, precisamos criar uma nova configuração para tudo funcionar corretamente.
Informar no AndroidManifest.xml
que usaremos uma configuração customizada para WorkManager
AndroidManifest.xml
<!--Dentro da Tag application-->
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
Feito isso vamos criar a configuração customizada.
Criando nova configuração para WorkManager
AppNameApplication.kt
@HiltAndroidApp
class AppNameApplication : Application() {
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration(): Configuration {
return Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
}
Agora sim está tudo pronto para funcionar, você tem uma classe Worker funcionando com injeção de dependências utilizando o Hilt. Parece muito trabalho mas num projeto onde temos vários workers facilita muito o desenvolvimento, Podemos injetar nosso Repository por exemplo e ainda tem a facilidade nos testes.
Detalhe importante
Até o momento as bibliotecas do Hilt não estavam funcionando bem com a biblioteca do kotlin versão 1.5.20 então usem á versão 1.5.10 que não gerou problemas.
Referências:
Posted on July 8, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.