2017-08-12 4 views
0

Mon objectif:Dagger2 sous-composante confusion dans Android

Pour comprendre comment fonctionne la portée et la façon de mettre en œuvre un UserScope que je peux utiliser sur plusieurs activités et réinitialiser/créer un nouveau si nécessaire.

Méthodes J'utilise:

  1. Ce Blog: http://frogermcs.github.io/building-userscope-with-dagger2/
    Il explique apparemment la même chose que je suis en train de réaliser ici.

  2. Docs officiels http://frogermcs.github.io/building-userscope-with-dagger2/

bref rapide sur le blog

De toute évidence, il est UserModule et UserComponent. Auteur a enveloppé la création de UserComponent sous UserManager qui a ApplicationScope. Donc UserManager est disponible au moment de la connexion. Lorsque la connexion est réussie UserComponent est initialisé via UserManager. Logique simple

Maintenant, ce @UserScope déjà initialisé est utilisé dans deux activités, comme vous pouvez le voir dans l'image.

Ce que je me bats pour comprendre

Jetez un oeil à UserComponent.

public interface UserComponent { 

    @Subcomponent.Builder 
    interface Builder { 
     Builder sessionModule(UserModule userModule); 

     UserComponent build(); 
    } 

    UserDetailsActivityComponent plus(UserDetailsActivityComponent.UserDetailsActivityModule module); 

    RepositoriesListActivityComponent plus(RepositoriesListActivityComponent.RepositoriesListActivityModule module); 

    LogoutManager logoutManager(); 
} 

Plus précisément UserDetailsActivityComponent et RepositoriesListActivityComponent sont créés par UserComponent. Comme cela,

@Override 
    protected void onUserComponentSetup(UserComponent userComponent) { 
     userComponent.plus(new UserDetailsActivityComponent.UserDetailsActivityModule(this)).inject(this); 
    } 

Alors ils ont d'abord obtenir une pré-créée en UserComponent par UserManager puis il appelle onUserComponentSetup qui crée alors le composant approprié et injecte l'activité en cours.

Je ne comprendre avec ce modèle mentionné ci-dessus, comme je l'ai lu dans les documents que nous utilisons plus(InjectionToBeDoneOn i) quand nous avons besoin de l'injection sur un cas particulier de InjectionToBeDoneOn. Mais pourquoi injecter cette activité via ce composant? Qu'est-ce que cela accomplit? Est-ce que cela n'aurait pas de sens de faire cela de manière conventionnelle en onCreate() de l'activité avec DaggerXYZComponent().Builder().Build().inject(activity)?

En outre, il me manque un matériau décent de la façon dont UserScope est mis en œuvre dans Android qui a une durée de vie de connexion à déconnexion, mais pas plus grande que la portée @Singleton.

Répondre

2

nous utilisons plus(InjectionToBeDoneOn i) quand nous avons besoin de l'injection sur cas particulier de InjectionToBeDoneOn

Pas tout à fait. Un composant a essentiellement trois types de méthodes

  1. SomeDependency provideDependency() qui vient de créer/offre une certaine dépendance à sous-composants, ou pour la recherche manuelle (essentiellement un getter)
  2. void inject(MyAndroidFrameworkClass object) qui injecte un objet avec ses dépendances
  3. SomeSubComponent plus(SubComponentModule module) que crée un sous-composant, en ajoutant des modules supplémentaires

Vous mélangez 2. et 3. ici.

// user scoped component 
userComponent 
    // create a subcomponent (UserDetailsActivityComponent) 
    .plus(new UserDetailsActivityComponent.UserDetailsActivityModule(this)) 
    // use the UserDetailsActivityComponent that was just created and inject with it 
    .inject(this); 

UserDetailsActivityComponent est une sous-composante de UserComponent, ce qui explique pourquoi le UserComponent est étendu .plus(somemodule) pour créer un sous-composant. Si votre sous-composant n'a pas besoin de modules supplémentaires, vous pouvez également utiliser .plus() car pour Dagger, l'élément important est le return type ou la signature en général.

  • S'il renvoie un autre composant, il crée un sous-composant.
  • Si elle as un paramètre et renvoie void ou le type de paramètres, il est un procédé d'injection
  • Si elle n'a pas de paramètres et renvoie un certain type est est une offre procédé (1) pour exposer une certaine dépendance

mais pourquoi injecter cette activité via ce composant? Qu'est-ce que cela accomplit?

Si vous deviez créer UserDetailsActivityComponent à partir de zéro, il ne verrait et savoir ce qu'il peut fournir lui-même . Si vous avez un @Singleton quelque part, il ne peut pas y accéder, car il ne fait pas partie du graphe d'objets.

Un sous-composant étend un autre composant, en ajoutant au graphique d'objet. Si vous avez un @Singleton A et votre UserComponentn a besoin A pour fournir B, avec un sous-composant cela fonctionnera, sans cela vous obtiendrez une erreur ne peut pas être fournie.

La dague n'est pas une magie. Il construit juste un graphique dirigé et vérifie si tout va bien. Il se plaindra si certaines dépendances ont des dépendances cycliques entre elles ou si une partie du graphe n'a pas accès aux dépendances dont il a besoin.

Votre UserComponent contient vos données d'utilisateur. Pour la simplicité, disons qu'il contient le UserName. Maintenant UserDetailsActivity peut vouloir afficher UserName, mais il faut un moyen de l'obtenir. En utilisant le @Singleton AppComponent en tant que parent, vous auriez accès à certains Apis, mais pas à ceux de l'utilisateur.Vous pouvez déplacer les objets délimités par l'utilisateur dans le @Singleton AppComponent, mais vous devrez ensuite recréer le AppComponent chaque fois que l'utilisateur change (ce qui est contraire au but de le déclarer @Singleton, ou vous devrez trouver d'autres moyens de mise à jour/modifier l'utilisateur.

Si vous voulez faire le chemin Dagger, vous créez un UserComponent que ajoute l'utilisateur au graphique. que les sous-composants façon peut y accéder et faire leurs choses utilisateur.

Lorsque l'utilisateur change, vous devez vous assurer de détruire toutes les activités/fragments qui ont utilisé le composant UserComponent, et vous recréer tout simplement — avec un nouvel utilisateur

habitude il judicieux de le faire de manière classique dans OnCreate() de l'activité avec DaggerXYZComponent().Builder().Build().inject(activity)

Vous pouvez le faire bien sûr. L'auteur a simplement mis les appels à app.getAppcomponent().getUserManager().getUserComponent() ou quelque chose comme ceci dans leur BaseActivity et BaseUserActivity afin que vous n'ayez pas à répéter les mêmes lignes de code à chaque fois. Cette méthode sera toujours appelée onCreate, elle vous permet simplement d'utiliser les composants directement, sans les récupérer à chaque fois.
Vous pouvez évidemment supprimer ces méthodes de modèle et tout intégrer dans onCreate, conduisant à un code dupliqué, rendant la maintenance plus difficile à long terme.

me manque matériel décent de la façon dont UserScope est mis en œuvre dans Android qui a la durée de vie de log-in pour ouvrir une session sur, mais pas plus grand que la portée @SingleTon.

Android n'aide pas et c'est à vous de faire le ménage après vous-même. Si l'utilisateur change, vous purgez tout ce que UserComponent et ses sous-composants ont touché, et recréez-le avec le nouvel utilisateur.

Vous devrez stocker le UserComponent avec l'utilisateur actuel dans la classe Application, un "vrai" singleton, ou un "Manager" dans le composant d'application avec une portée @Singleton. Chaque approche a ses propres avantages, je suppose.

Les portées signalent simplement à Dagger qu'un objet devrait exister dans une portée seulement une fois. Peu importe ce que vous nommez, ou combien d'objets sont dans la portée. Dagger a seulement besoin d'eux pour s'assurer qu'il n'y a pas de cycles de dépendance.

+0

Cela a du sens. Je vous remercie. mais 'UserModule' n'a pas d'attribut' subcomponents' pour 'UserDetailsActivityComponent', comme mentionné dans les Docs, mais toujours' UserDetailsActivityComponent' peut servir de sous-composant de 'UserComponent'? – Ankit

+0

@Ankit Je ne comprends pas très bien de quoi vous parlez. Pourriez-vous élaborer votre question? –

+0

cela provient du document 'Pour ajouter un sous-composant à un composant parent, ajoutez la classe de sous-composant à l'attribut sous-composants d'un @Module que le composant parent installe. Ensuite, le constructeur du sous-composant peut être demandé à partir du parent. »C.-à-d.' @Module (sous-composants = RequestComponent.class) ' – Ankit