Escolar Documentos
Profissional Documentos
Cultura Documentos
Chapter 4 - Managing Dependencies in Android Applications - Clean Android Architecture
Chapter 4 - Managing Dependencies in Android Applications - Clean Android Architecture
Capítulo 4 : Gerenciando
dependências em aplicativos Android
Introdução ao DI
Usando o Dagger 2 para gerenciar dependências
Usando Hilt para gerenciar dependências
Requerimentos técnicos
Introdução ao DI
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 1/25
26/10/2022 21:42 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
Nesta seção, veremos o que é a DI, os benefícios que ela oferece e como esse
conceito é aplicado a umAplicativo Android. Em seguida, veremos algumas bi-
bliotecas de DI e como elas funcionam.
class ClasseA(){
valor privado b: ClassB = ClassB()
divertido executeA() {
b.executeB()
}
}
classe ClasseB(){
divertido executeB() {
}
}
Neste exemplo, ClassA cria uma nova instância de ClassB e, em seguida,
quando executeA é invocado, ele invocará executeB . Isso representa um pro-
blema porque ClassA terá a responsabilidade extra de criar ClassB . Vamos ver
o que acontece se ClassB precisar mudar para algo como o seguinte:
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 2/25
26/10/2022 21:42 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
class ClasseA(){
valor privado b: ClassB = ClassB(true)
divertido executeA() {
b.executeB()
}
}
Aqui, precisaremos fornecer um valor booleano quando criarmos ClassB .
Fazer esses tipos de alterações em um aplicativo à medida que sua base de có-
digo aumenta dificultará a manutenção. Uma solução para esse problema é se-
parar como usamos dependências e como as criamos e delegar a criação a um
objeto diferente. Continuando com o exemplo anterior, podemos reescrever
ClassA da seguinte forma:
class Injetor() {
divertido criarA(b: ClasseB) = ClasseA(b)
fun createB() = ClassB(true)
}
Aqui, temos uma nova classe que criará uma instância de ClassA com ClassB
como parâmetro e um método separado para criar uma instância de ClassB .
Idealmente, quando o programafor inicializado, precisaríamos inicializar to-
das as dependências e passá-las adequadamente:
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 3/25
26/10/2022 21:42 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
class Injetor() {
divertido criarA(b: ClasseB) = ClasseA(b)
divertido createB() = ClassB1()
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 4/25
26/10/2022 21:42 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
}
No método createB , retornamos uma instância de ClassB1 , que será posterior-
mente injetada em ClassA . Isso representa mais um benefício da DI, onde po-
demos fazer com que nosso código dependa deabstrações ao invés de concre-
ções e fornecem concreções diferentes para propósitos diferentes. Com base
nisso, podemos definir os seguintes papéis quando se trata de DI:
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 5/25
26/10/2022 21:42 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
Nesta seção, apresentamos o padrão DI, como ele funciona e os problemas que
está resolvendo. Os desenvolvedores podem gerenciar as dependências e a in-
jeção de um aplicativo manualmente, configurando injetores. Mas à medida
que um aplicativo cresce, torna-se difícil mantê-lo, especialmente quandoque-
remos que certos objetos vivam apenas enquanto outros objetos e não en-
quanto o aplicativo, ou manipule diferentes instâncias da mesma classe. Exis-
tem vários frameworks e bibliotecas de DI que podem gerenciar todos esses
casos e no Android, um dos mais usados é o Dagger 2.
Nesta seção, nósirá analisar a biblioteca Dagger 2, comoele lida com DI, como
funciona, como é integrado a um aplicativo Android e quais problemas ele
pode criar.
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 6/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
plug-ins {
…
id 'kotlin-kapt'
…
}
Aqui, adicionamos o plug-in kotlin-kapt para permitir que o Dagger 2 gere o
código necessário para DI. Em seguida, precisaremos das dependências do
Dagger 2:
dependências {
…
implementação 'com.google.dagger:dagger:2.40.5'
kapt 'com.google.dagger:dagger-compiler:2.40.5'
…
}
Aqui, estamos adicionando uma dependência à biblioteca Dagger 2 e uma de-
pendência à biblioteca de processamento de anotações, que tem a função de
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 7/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
geração de código. A versão da biblioteca deve ser a versão estável mais re-
cente disponível no repositório da biblioteca.
@Módulo
class ApplicationModule {
@Provides
fun provideClassA(b: ClassB): ClassA = ClassA(b)
@Provides
fun provideClassB(): ClassB = ClassB1()
}
Aqui, anotamosa classe com @Module e paracada instância, usamos a anotação
@Provides . Podemos simplificar ainda mais com a anotação @Inject e excluir
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 8/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
@Módulo
classe abstrata ApplicationModule {
@Binds
diversão abstrata bindClassB(b: ClassB1): ClassB
}
Aqui, adicionamos o método abstrato bindClassB , que é anotado com @Binds .
Este método dirá ao Dagger 2 para conectar a implementação ClassB1 com a
abstração ClassB . Para evitar grandes anotações @Provides , devemos tentar
usar a anotação para dependências onde não podemos modificar o código e,
em vez disso, confiar em @Inject nos construtores e usar @Binds sempre que
possível.
@Singleton
@Component(modules = [ApplicationModule::class])
interface ApplicationComponent
Aqui, estamos definindo um @Component no qual especificamos o módulo que o
aplicativo usará. A anotação @Singleton diz ao Dagger que todas as dependên-
cias neste componente viverão enquanto o aplicativo. Neste ponto, devemos
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 9/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
@Singleton
@Component(modules = [ApplicationModule::class])
interface ApplicationComponent {
fun injetar(mainActivity: MainActivity)
}
Em ApplicationComponent , adicionamos um método chamado inject e a
Activity onde queremos que a injeção seja realizada. Na classe MainActivity ,
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 10/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
(aplicação como
MyApplication).component.inject(this)
a.executeA()
}
}
Aqui, precisaremos acessar a instância ApplicationComponent criada em
MyApplication e, em seguida, invocar o método inject de ApplicationCompo‐
nent . Isso inicializará a variável a com a instância Dagger 2 criada. Essa abor-
@Alcance
@MustBeDocumented
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
classe de anotação ActivityScope
Aqui, criamos uma nova anotação @Scope , que indicará que as dependências
durarão tanto quanto as atividades. Em seguida, usaremos @ActivityScope
para criar uma classe anotada @Subcomponent :
@ActivityScope
@Subcomponent(modules = [ApplicationModule::class])
interface MainSubcomponent {
fun injetar(mainActivity: MainActivity)
}
Aqui, temosdefiniu um subcomponenteque usará ApplicationModule e possui
um método de injeção para injeção de campo em MainActivity . Depois disso,
precisaremos dizer ao Dagger 2 para criar MainSubcomponent , modificando Ap‐
plicationComponent :
@Singleton
@Componente
interface ApplicationComponent {
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 11/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
gura a seguir:
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 12/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
Na figura anterior, podemos ver que o Dagger irá gerar a implementação para
a interface ApplicationComponent , bem como a implementação MainSubcompo‐
nent . Pordependências que precisarãoser injetado, ele irá gerar uma classe
membros, ele criará uma classe Injector , que será responsável por definir o
valor na variável membro, como a classe MainActivity .
Nesta seção, discutimos a biblioteca Dagger 2 e como ela pode ser usada para
fornecer e injetar dependências. Por ser uma biblioteca usada em outros fra-
meworks além do Android, ela requer soluções específicas para injetar ativi-
dades e fragmentos, usando injetores de membros e subcomponentes. Uma
tentativa de corrigir isso foi através da introdução da biblioteca Android Dag-
ger, que tratou da criação de classes anotadas @Subcomponent e introduziu no-
vas anotações para indicar como os subcomponentes devem ser criados. Mais
recentemente, a introdução da biblioteca Hilt foi maiseficaz para resolver es-
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 13/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
quanto o aplicativo.
@ViewModelComponent : Isso fará com que as dependências vivam en-
quanto um ViewModel .
@ActivityComponent : Isso fará com que as dependências vivam en-
quanto um Fragment .
@ServiceComponent : Isso fará com que as dependências vivam enquanto
um Service .
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 14/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
script de construção {
repositórios {
…
}
dependências {
…
classpath 'com.google.dagger:hilt-android-gradle-
plug-in: 2.40.5'
}
}
Em seguida, precisaremos adicionar o plug-in do processador de anotações e o
plug-in Hilt ao arquivo build.gradle do módulo Gradle no qual queremos usar
a biblioteca Hilt:
plug-ins {
…
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
A combinação destes dois plugins é o que permite ao Hilt gerar a fonte neces-
sáriacódigo para injetar as dependências. Finalmente, nósprecisará adicionar
a dependência à biblioteca Hilt:
dependências {
…
implementação 'com.google.dagger:hilt-android:2.40.5'
kapt 'com.google.dagger:hilt-compiler:2.40.5'
…
}
Aqui, precisamos da dependência da própria biblioteca e uma dependência do
processador de anotações, como era necessário para o Dagger 2.
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 15/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
@Módulo
@InstallIn(SingletonComponent::class)
classe abstrata ApplicationModule {
@Binds
diversão abstrata bindClassB(b: ClassB1): ClassB
}
Na classe ApplicationModule , mantemos a mesma implementação de antes,
mas agora adicionamos a anotação @InstallIn , que tornará as dependências
fornecidas por este módulo ativas enquanto o aplicativo estiver. Em seguida,
precisaremos acionar a geração de componentes:
@HiltAndroidApp
class MeuAplicativo: Aplicativo()
Aqui, não precisamos mais usar DaggerApplicationComponent para acionar ma-
nualmente ocriação do gráfico de dependência e, em vez disso,use
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 16/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
@HiltAndroidApp , que fará isso por nós, além de fornecer a capacidade de inje-
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Injetar
lateinit var a: ClassA
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
a.executeA()
}
}
Aqui, usamos o ponto @AndroidEntry para informar ao Hilt que queremos inje-
tar uma dependência em uma Activity e, em seguida, usar a anotação @Inject
como funcionava no Dagger 2. O código gerado pelo Hilt será semelhante à fi-
gura a seguir e pode ser encontrado em
{module}/build/generated/source/kapt/{build type} :
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 17/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
Nesta seção, discutimos a biblioteca Hilt, como podemos usá-la para gerenciar
dependências em um aplicativo Android e como ela remove o código padrão
que o Dagger 2 exigia. Na seção a seguir, veremos um exercício sobre a inte-
gração do Hilt em um aplicativo junto com outras bibliotecas.
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 18/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 19/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
Aqui, adicionamos uma dependência que permite que o Hilt trabalhe com a
biblioteca Jetpack Compose Navigation.
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 20/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
.addConverterFactory(MoshiConverterFactory.cre
ate
(moshi))
.construir()
@Provides
fun fornecerUserService(retrofit: Retrofit):
Serviço de usuário =
retrofit.create(UserService::class.java)
}
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 21/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 22/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
) : ViewModel() {
…
}
10. Exclua a referência a MainViewModelFactory no método Users @Composable
em MainActivity :
@Composable
usuários divertidos (
navController: NavController,
viewModel: MainViewModel
) {
…
}
11. Mudaro método @Composable Appem MainActivity para que ele forneça uma
instância MainViewModel ao invocar o método Users :
@Composable
App divertido(navController: NavHostController) {
NavHost(navController, startDestination =
AppNavigation.Users.route) {
composable(route = AppNavigation.Users.route)
{
Usuários(navController, hiltViewModel() )
}
combinável(
rota = AppNavigation.User.route,
argumentos = listOf(navArgumento
(AppNavigation.User.argumentName) {
tipo = NavType.StringType
})
) {
User(it.arguments?.getString(AppNavigation
.User.
argumentName).ouEmpty())
}
}
}
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 23/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
Esse erro é causado por uma incompatibilidade que existe atualmente nas fer-
ramentas de compilação do Android e deve ser resolvido quando atualizações
posteriores estiverem disponíveis.
Resumo
In this chapter, we looked at the DI pattern and some of the more popular li-
braries that are available to apply this pattern to an Android application. We
looked initially at Dagger 2 and how it can be integrated into an application,
and then we analyzed the Hilt library, which is built on top of Dagger 2 and
solves further problems that are specific to Android development.
Existem outras bibliotecas que podem ser usadas para gerenciar dependên-
cias, como a Koin, que usa o padrão Service Locator (no qual um registro é cri-
ado e as dependências podem ser obtidas) e é desenvolvida para desenvolvi-
mento Kotlin. O exercício deste capítulo mostrou como o Hilt pode ser inte-
grado a outras bibliotecas em um aplicativo Android. O problema é que o apli-
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 24/25
26/10/2022 21:43 Chapter 4: Managing Dependencies in Android Applications | Clean Android Architecture
cativo ainda não tem forma; não há nada que possamos apontar que indique
quais são os casos de uso. Nos capítulos a seguir, veremos como podemos es-
truturar nosso código para dar-lhe uma forma usando os princípios da Arqui-
tetura Limpa, começando com a definição de entidades e casos de uso.
Apoiar Sair
https://learning.oreilly.com/library/view/clean-android-architecture/9781803234588/B18320_04_ePub.xhtml 25/25