O punhal 2 é elementar (parte 2)

Parte anterior

Conteúdo

  1. Implementar métodos e campos
  2. Inicialização atrasada no punhal
  3. Módulos do punhal. Quando a adaga não te entende
  4. Resumo nomeado. Várias instâncias do mesmo tipo

Implementar métodos e campos

A primeira parte descreve um método para implementar dependência no nível do construtor. Além disso, o punhal pode implementar dependências para campos e métodos. Mas essas implementações devem ser usadas quando for absolutamente necessário.

Exemplo de implementação de método:

class Car @Inject constructor(private var engine: Engine){ var key: Key? = null @Inject set } class Key @Inject constructor() 

No exemplo acima, a dependência do método definido é implementada para o campo-chave

A implementação dos campos ocorre em três etapas:

  1. Adicionar método de incorporação à fábrica abstrata
  2. Definir campos a serem implementados
  3. Use métodos de implementação em uma implementação de adaga de classe abstrata para implementar dependências

Será claramente mais fácil entender isso, a fim de

1. Em nossa classe abstrata, adicione um método de implementação para MainActivity

 @Component interface DaggerComponent { fun getCar(): Car fun getEngine(): Engine fun getFuel(): Fuel fun inject(act: MainActivity) } 

2. Defina os campos que devem ser implementados no MainActivity. Os campos injetados devem ter lateinit var e estar visíveis para todos (público)

 @Injected lateinit var car: Car 

3. Chamamos o método adicionado de injetar () da classe abstrata para implementar os campos de atividade.

Por fim, nossa classe MainActivity parecerá um rastreamento. caminho:

 class MainActivity : AppCompatActivity() { @Inject lateinit var car: Car override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) DaggerDaggerComponent.create().inject(this) } } 

Inicialização atrasada no punhal

Como você sabe, ao iniciar um aplicativo, nem sempre são necessárias instâncias de todas as classes. Isso acelera o primeiro lançamento e muito mais. Existem 2 tipos de inicialização de objetos incorporados no punhal: Provedor <> E Preguiçoso <>

Provedor - a inicialização ocorre na primeira chamada ao objeto e a cada chamada uma nova instância do objeto será retornada
Preguiçoso - a inicialização ocorre na primeira chamada e as instâncias armazenadas em cache anteriormente são retornadas

Para usar esses tipos de inicialização, é necessário "quebrar" os objetos inicializados no formato desejado.

Exemplo de uso do provedor:

 class Engine @Inject constructor(private var fuel: Fuel){ fun start(){ if(fuel!=null){ print("Started!") }else{ print("No more fuel!") } } } class Car @Inject constructor(private var engine: Provider<Engine>){ var key: Key? = null @Inject set fun startCar(){ engine.get().start() } } class Key @Inject constructor() 

Cada vez que o método get () é chamado, obtemos uma nova instância do objeto desejado.

Um exemplo de uso do Lazy:

 class Fuel @Inject constructor() { val fuelType = if(BuildConfig.DEBUG){ "benzine" }else{ "diesel" } } class Engine @Inject constructor(private var fuel: Lazy<Fuel>){ fun start(){ if(fuel!=null){ print("Started with ${fuel.get().fuelType}") }else{ print("No more fuel!") } } } 

Cada vez que o método get () é chamado, obtemos a mesma instância.

Atenção! Ao adicionar o método get () da exibição Lazy no Android Studio, o método pode ser sublinhado em vermelho, pois Kotlin tem sua própria classe Lazy. Então importamos a classe punhal

 import dagger.Lazy 

Módulos do punhal. Quando a adaga não te entende

Há momentos em que uma adaga não entende suas intenções. Por exemplo, nossa classe Car tem um campo do tipo Driver (interface), que é herdado pela classe Ivanov

Ao tentar implementar um campo com um tipo de interface, você obtém o erro "não pode ser fornecido sem os métodos anotados em @ Fornece".

Para resolver esse problema, o punhal sugere o uso de módulos. Os módulos fornecem ao punhal informações adicionais que ele não pode obter por si só. Como módulos, você pode usar interfaces ou objetos (objeto).

Para resolver o problema acima, crie um módulo:

 @Module interface DaggerModul { @Binds fun bindDriver(driver: Ivanov): Driver } class Ivanov @Inject constructor(): Driver 

No método bindDriver, explicamos ao punhal como inicializar a interface.

Também no componente, você precisa listar todos os módulos de adagas existentes

 @Component(modules = [DaggerModul::class]) interface DaggerComponent { … } 

Suponha que, para nossa classe Engine, o campo do cilindro da biblioteca de terceiros (interface) seja usado. Como descrever esse campo para o punhal, se não está claro qual classe será inicializada em tempo de execução?

Até agora, usamos anotações para explicar como punhais como dependências devem ser injetadas. E se você não souber como criar classes a partir de bibliotecas estrangeiras, por exemplo?

Fornece anotação descreve os casos em que você precisa descrever explicitamente uma instância da classe que deseja inicializar.

 @Module object DaggerModuleObject { @Provides @JvmStatic fun getBoschCylinder(): Cylinder = BoschCylinder() } 

Assim, dizemos ao punhal que, ao inicializar o campo do cilindro, precisamos de uma instância da classe BoschCylinder.

Resumo nomeado . Várias instâncias do mesmo tipo

Há momentos em que você precisa criar instâncias da mesma classe com configurações diferentes. No nosso exemplo, essas são cores diferentes no corpo e nas portas.

Ao tentar criar um projeto com um rastreio. O módulo receberá o erro "(nossa classe) A cor é vinculada várias vezes"

 @Provides @JvmStatic fun getColorRed():Color = Color("red") @Provides @JvmStatic fun getColorBlue():Color = Color("blue") 

Para resolver esses casos, a anotação Nomeada é usada. Primeiro de tudo, no módulo, criaremos 3 novos métodos para inicialização no punhal

 @JvmStatic @Provides fun getColor(): Color = Color("") @Provides @Named("blueColor") @JvmStatic fun getColorBlue(): Color{ return Color("blue") } @JvmStatic @Named("redColor") @Provides fun getColorRed(): Color = Color("red") 

O primeiro método é o padrão, sem ele o punhal jura pela ausência da classe "não pode ser fornecida sem um construtor Inject ou um método anotado por Fornece"

Os dois métodos a seguir retornam instâncias da mesma classe. Resta adicionar a implementação desta classe nos lugares certos e chamar com a anotação Nome

 class Door @Inject constructor() { @Named("blueColor") @Inject lateinit var color:Color } class Car @Inject constructor(private var engine: Provider<Engine>, private var door: Door, var driver: Driver){ var key: Key? = null @Inject set @Inject @Named("redColor") lateinit var color: Color fun startCar(){ engine.get().start() } } class Key @Inject constructor() 

Código fonte

Source: https://habr.com/ru/post/pt466769/


All Articles