Parte anteriorConteúdo
- Implementar métodos e campos
- Inicialização atrasada no punhal
- Módulos do punhal. Quando a adaga não te entende
- Resumo nomeado. Várias instâncias do mesmo tipo
Implementar métodos e camposA 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:
- Adicionar método de incorporação à fábrica abstrata
- Definir campos a serem implementados
- 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 punhalComo 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 entendeHá 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 tipoHá 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