Utilizando WorkManager com Hilt - Injeção de dependência  na classe Worker
Tags: android, kotlin, hilt, workmanager
Published: 2021-07-08 04:30:39

##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)`
```kotlin
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.
```kotlin
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
```Kotlin
//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)`
```Kotlin
buildscript {
    //...
    dependencies {
        //...
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.37'
    }
}

```

---

`build.gradle(Module)`
```Kotlin
//...
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`
```kotlin
@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`
```kotlin
@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](https://developer.android.com/training/dependency-injection/hilt-android)

###Preparando a classe `SomeWork` para receber a injeção de dependência.
```kotlin
@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`
```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`
```kotlin
@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:
* [HiltWorker](https://developer.android.com/reference/androidx/hilt/work/HiltWorker)
* [Hilt](https://developer.android.com/training/dependency-injection/hilt-android)
* [workmanager](https://developer.android.com/topic/libraries/architecture/workmanager)