2017-09-13 3 views
1

Je lis this super tutoriel qui explique comment fonctionne @Component.Builder dans Dagger 2. L'auteur a fait du bon travail et l'article est simple, mais il y a encore une certaine confusion, je dois clarifier : l'implémentation par défaut de Dagger 2 ressemble à ceci:Comprendre poignard 2 @ Annotation Component.Builder

le composant:

@Singleton 
@Component(modules = {AppModule.class}) 
public interface AppComponent { 

    void inject(MainActivity mainActivity); 
    SharedPreferences getSharedPrefs(); 
} 

le module:

@Module 
public class AppModule { 

    Application application; 

    public AppModule(Application application) { 
     this.application = application; 
    } 

    @Provides 
    Application providesApplication() { 
     return application; 
    } 
    @Provides 
    @Singleton 
    public SharedPreferences providePreferences() { 
     return application.getSharedPreferences(DATA_STORE, 
           Context.MODE_PRIVATE); 
    } 
} 

instanciation Composant:

DaggerAppComponent appComponent = DaggerAppComponent.builder() 
     .appModule(new AppModule(this)) //this : application 
     .build(); 

Selon l'article, nous pouvons simplifier le code encore plus en évitant les arguments passant au constructeur du module en utilisant @Component.Builder et @BindsInstance annotations, le code ressemblera à ceci:

le composant:

@Singleton 
@Component(modules = {AppModule.class}) 
public interface AppComponent { 
    void inject(MainActivity mainActivity); 
    SharedPreferences getSharedPrefs(); 

    @Component.Builder 
    interface Builder { 
     AppComponent build(); 
     @BindsInstance Builder application(Application application);  
    } 

}

la m Théodule:

@Module 
public class AppModule { 

    @Provides 
    @Singleton 
    public SharedPreferences providePreferences(
            Application application) { 
     return application.getSharedPreferences(
            "store", Context.MODE_PRIVATE); 
    } 
} 

Et le composant instanciation:

DaggerAppComponent appComponent = DaggerAppComponent.builder() 
      .application(this) 
      .build(); 

Je comprends presque comment fonctionne le code ci-dessus, mais voici la partie que je ne comprends pas: comment avons-nous appModule(new AppModule(this))-application(this) quand nous instancions le composant?

J'espère que la question était claire et merci.

Répondre

4

tl; dr Dagger ne créera un no-arg modèles du constructeur lui-même si vous ne les passez pas et l'utilisation de @BindsInstance peut-être mieux optimisé que de fournir des types d'un module.


D'abord, vous aviez un composant nécessitant la construction d'un Application. Vous construisez donc le module et le transmettez au composant. Maintenant, avec le générateur de composants, vous pouvez simplement lier à un composant. C'est une alternative à ce que nous avons fait ci-dessus. Il n'y a plus besoin d'un module et nous pouvons simplement donner directement à Dagger l'objet que nous voulons dans notre composant.
Comme avec @Binds pour fournir des implémentations d'interface, vous pouvez souvent supposer que Dagger peut et va optimiser les fonctionnalités comme celles mieux que la simple approche utilisant un module, puisque l'intention est plus clairement marquée.

Donc, en utilisant le @BindsInstance ajoutera le type à notre composant de sorte que nous n'avons plus besoin du module pour le fournir. Nous pouvons maintenant également supprimer le paramètre du constructeur du module.

Comment avons-nous de AppModule (nouveau AppModule (ce)) à l'application (ce) lorsque nous sommes instancié avec le composant?

Depuis Dagger peut instancier modules non-args se il n'y a plus la nécessité d'ajouter explicitement le module au composant, et nous pouvons remplacer cette ligne avec le nouvel appel .application(this).

+0

Si Dagger peut instancier modules non-args lui-même, nous utilisons froid juste 'DaggerAppComponent.builder() build();.', Donc ce ' l'application (ceci) est pour alors? –

+0

Vérifiez votre interface 'Component.Builder'! Vous enregistrez une méthode qui lie l'application au composant, que vous devez appeler: 'Application @BindsInstance Builder (application Application);' –

+0

Maintenant, je vois! Merci beaucoup David Medenjak vous étiez très utile –

0
@Component.Builder 
    interface Builder { 
     AppComponent build(); 
     @BindsInstance Builder application(Application application);  
    } 

Lorsque nous appelons la méthode

demande

(Application Application)

de la classe d'application

.Application (this)

Il va définir notre objet d'application à l'AppComponent. Donc, dans l'appcomponet, l'instance d'application est disponible.

Nous pouvons donc supprimer le code ci-dessous du module d'application, car Dagger injectera automatiquement l'instance d'application là où elle sera nécessaire.

Application application; 
    public AppModule(Application application) { 
     this.application = application; 
    } 

    @Provides 
    Application providesApplication() { 
     return application; 
    } 

Également, Dagger instancie tous les modules avec le constructeur par défaut.

Si vous voulez un objet de contexte de AppModule il suffit d'écrire

@Module 
public class AppModule { 

    @Provides 
    Context provideContext(Application application) { 
     return application; 
    } 
}