Partie précédenteTable des matières
- Implémenter des méthodes et des champs
- Initialisation retardée dans la dague
- Modules de poignard. Quand le poignard ne te comprend pas
- Résumé nommé. Plusieurs instances du même type
Implémenter des méthodes et des champsLa première partie décrit une méthode pour implémenter la dépendance au niveau constructeur. De plus, la dague peut implémenter des dépendances pour les champs et les méthodes. Mais ces implémentations doivent être utilisées lorsque cela est absolument nécessaire.
Exemple d'implémentation de la méthode:
class Car @Inject constructor(private var engine: Engine){ var key: Key? = null @Inject set } class Key @Inject constructor()
Dans l'exemple ci-dessus, la dépendance de méthode définie est implémentée pour le champ clé
La mise en œuvre des champs se déroule en trois étapes:
- Ajouter la méthode d'intégration à la fabrique abstraite
- Définir les champs à mettre en œuvre
- Utiliser des méthodes d'implémentation dans une implémentation de poignard de classe abstraite pour implémenter des dépendances
Il sera clairement plus facile de comprendre cela, afin
1. Dans notre classe abstraite, ajoutez une méthode d'implémentation pour MainActivity
@Component interface DaggerComponent { fun getCar(): Car fun getEngine(): Engine fun getFuel(): Fuel fun inject(act: MainActivity) }
2. Définissez les champs qui doivent être implémentés dans MainActivity. Les champs injectés doivent être var tardifs et visibles par tous (public)
@Injected lateinit var car: Car
3. Nous appelons la méthode ajoutée inject () de la classe abstraite pour implémenter les champs d'activité.
En fin de compte, notre classe MainActivity ressemblera à une trace. façon:
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) } }
Initialisation retardée dans la dagueComme vous le savez, lors du démarrage d'une application, les instances de toutes les classes ne sont pas toujours nécessaires. Cela accélère le premier lancement et plus encore. Il existe 2 types d'initialisation des objets incorporés dans la dague: le fournisseur <> et lazy <>
Fournisseur - l'initialisation se produit lors du premier appel à l'objet et à chaque appel une nouvelle instance de l'objet sera retournée
Paresseux - l'initialisation se produit lors du premier appel, puis les instances précédemment mises en cache sont renvoyées
Pour utiliser ces types d'initialisation, il est nécessaire de "boucler" les objets initialisés sous la forme souhaitée.
Exemple d'utilisation du fournisseur:
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()
Chaque fois que la méthode get () est appelée, nous obtenons une nouvelle instance de l'objet souhaité.
Un exemple d'utilisation de 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!") } } }
Chaque fois que la méthode get () est appelée, nous obtenons la même instance.
Attention! Lors de l'ajout de la méthode get () de la vue Lazy dans Android Studio, la méthode peut être soulignée en rouge car Kotlin a sa propre classe Lazy. Nous importons donc la classe poignard
import dagger.Lazy
Modules de poignard. Quand le poignard ne te comprend pasIl y a des moments où un poignard ne comprend pas vos intentions. Par exemple, notre classe Car possède un champ de type (interface) Driver, hérité de la classe Ivanov
Lorsque vous essayez d'implémenter un champ avec un type d'interface, vous obtenez l'erreur «ne peut pas être fourni sans une méthode annotée @ Provides».
Pour résoudre ce problème, le poignard suggère d'utiliser des modules. Les modules fournissent au poignard des informations supplémentaires qu'il ne peut pas obtenir par lui-même. En tant que modules, vous pouvez utiliser des interfaces ou des objets (objet).
Pour résoudre le problème ci-dessus, créez un module:
@Module interface DaggerModul { @Binds fun bindDriver(driver: Ivanov): Driver } class Ivanov @Inject constructor(): Driver
Dans la méthode bindDriver, nous expliquons à la dague comment initialiser l'interface.
Dans le composant, vous devez également répertorier tous les modules de poignard existants
@Component(modules = [DaggerModul::class]) interface DaggerComponent { … }
Supposons que pour notre classe Engine, le champ du cylindre de bibliothèque tiers (interface) soit utilisé. Comment décrire un tel champ pour dagger s'il n'est pas clair quelle classe sera initialisée en runtime?
Jusqu'à présent, nous avons utilisé l'annotation pour expliquer à la dague comment les dépendances doivent être injectées. Et si vous ne savez pas comment créer des classes à partir de bibliothèques étrangères, par exemple?
Fournit une annotation qui décrit ces cas lorsque vous devez décrire explicitement une instance de la classe que vous souhaitez initialiser.
@Module object DaggerModuleObject { @Provides @JvmStatic fun getBoschCylinder(): Cylinder = BoschCylinder() }
Ainsi, nous disons au poignard que lors de l'initialisation du champ cylindre, nous avons besoin d'une instance de la classe BoschCylinder.
Résumé nommé . Plusieurs instances du même typeIl y a des moments où vous devez créer des instances de la même classe avec des paramètres différents. Dans notre exemple, ce sont des couleurs différentes sur la carrosserie et les portes.
Lorsque vous essayez de créer un projet avec une trace. Le module recevra l'erreur "(notre classe) La couleur est liée plusieurs fois"
@Provides @JvmStatic fun getColorRed():Color = Color("red") @Provides @JvmStatic fun getColorBlue():Color = Color("blue")
Pour résoudre de tels cas, l'annotation
nommée est utilisée. Tout d'abord, dans le module nous allons créer 3 nouvelles méthodes d'initialisation en poignard
@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")
La première méthode est la méthode par défaut, sans elle la dague jurera de l'absence de la classe "ne peut pas être fournie sans un constructeur Inject ou une méthode annotée par Provides"
Les deux méthodes suivantes renvoient des instances de la même classe. Il reste à ajouter l'implémentation de cette classe aux bons endroits et à appeler avec l'annotation
Nommée 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()
Code source