J'ai regardé quelques articles différents qui semblent suggérer deux façons différentes de faire un cadrage personnalisé dans Dagger 2:
Présentateurs MVP qui survivent aux changements de configuration, partie 2 ( Repo Github ):
@Hello1Scope
et @Hello2Scope
pour Hello1Fragment
et Hello2Fragment
respectivementDasting Dagger 2 sur Android :
@PerFragment
.D'après ce que je comprends, il semble que, comme dans la méthode 2, il devrait être correct d'avoir une seule portée définie qui peut être utilisée pour tous les fragments (c'est-à-dire @PerFragment
). En fait (veuillez me corriger si je me trompe), il semble que le nom de l'étendue personnalisée ne soit pas pertinent, et ce n'est que là où le sous-composant est créé (c'est-à-dire dans Application, Activité ou Fragment) qui compte.
Existe-t-il un cas d'utilisation pour définir une portée unique pour chaque fragment, comme dans le cas 1?
Après avoir lu la réponse de @vaughandroid, et Qu'est-ce qui détermine le cycle de vie d'un composant (graphique d'objet) dans Dagger 2? Je pense que je comprends assez bien les étendues personnalisées pour répondre à ma propre question.
Tout d'abord, voici quelques règles concernant les composants, les modules et les annotations de portée dans dagger2.
@Singleton
ou @CustomScope
).@Singleton
pour le composant racine (et ses modules) uniquement. Les sous-composants doivent utiliser une étendue personnalisée, mais la fonctionnalité de cette étendue est exactement la même que @Singleton
.Maintenant, pour répondre à la question: je dirais créer une nouvelle étendue nommée pour chaque étendue conceptuellement différente. Par exemple, créez un @PerActivity
, @PerFragment
, ou @PerView
annotation qui indique où le composant doit être instancié, et indique ainsi sa durée de vie.
Remarque : il s'agit d'un compromis entre deux extrêmes. Considérons le cas d'un composant racine et des sous-composants n dont vous aurez besoin:
@Singleton
et @SubSingleton
), et@Singleton
, @SubSingleton1
, ... @SubSingletonN
).Application:
/** AppComponent.Java **/
@Singleton
@Component( modules = AppModule.class )
public interface AppComponent{
void inject(MainActivity mainActivity);
}
/** AppModule.Java **/
@Module
public class AppModule{
private App app;
public AppModule(App app){
this.app = app;
}
// For singleton objects, annotate with same scope as component, i.e. @Singleton
@Provides @Singleton public App provideApp() { return app; }
@Provides @Singleton public EventBus provideBus() { return EventBus.getDefault(); }
}
Fragment:
/** Fragment1Component.Java **/
@PerFragment
@Component( modules = {Fragment1Module.class}, dependencies = {AppComponent.class} )
public interface Fragment1Component {
void inject(Fragment1 fragment1);
}
/** Fragment1Module.Java **/
@Module
public class Fragment1Module {
// For singleton objects, annotate with same scope as component, i.e. @PerFragment
@Provides @PerFragment public Fragment1Presenter providePresenter(){
return new Fragment1Presenter();
}
}
/** PerFragment.Java **/
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerFragment {}
Votre compréhension est correcte. Les étendues nommées vous permettent de communiquer votre intention, mais elles fonctionnent toutes de la même manière.
La durée de vie de l'instance Component est cependant importante. 2 instances différentes du même composant fourniront des instances d'objets différentes, même de portée.
Les noms d'étendue doivent indiquer la durée de vie de l'objet fourni (qui correspond à celle de l'instance Component) donc @PerFragment
est beaucoup plus logique pour moi.
D'un rapide coup d'œil au didacticiel "MVP Presenters ...", il n'est pas clair pour moi quelle est exactement l'intention de l'auteur d'avoir des portées distinctes. Puisque les noms sont juste jetables, je ne lirais pas trop dedans.