32 votes

Poignard 2 Injection De Constructeurs

Je commence à utiliser la Dague 2 dans une application que je suis en développement, mais j'ai quelques questions sur la façon dont la Dague 2 fonctionne.

Je reçois le tout la logique derrière le @Fournit des méthodes et de l'annotation @Inject pour initialisation de vos dépendances, mais l'annotation @Inject pour les constructeurs de classe genre de bugs de mon esprit.

Par exemple:

Im mon application, j'ai un module défini, le ContextModule, pour récupérer le contexte de ma demande:

ContextModule.java

@Module
public class ContextModule {

    private final Context context;

    public ContextModule(Context context) {
        this.context = context;
    }

    @Provides
    public Context context() {
        return this.context;
    }
}

Ce module est utilisé par mon BaseActivityComponent:

BaseActivityComponent.java

@BaseActivityScope
@Component(modules = ContextModule.class)
public interface BaseActivityComponent {
    void injectBaseActivity(BaseActivity baseActivity);
}

Jusqu'ici tout va bien.. alors j'ai une action authcontroller classe, qui dépend du contexte et des je veux de l'injecter dans mon BaseActivity. Donc, dans mon AuthControllers.class j'ai quelque chose comme:

public class AuthController {

    private Context context;

    @Inject
    public AuthController(Context context) {
        this.context = context;
    }

    public void auth() {
        // DO STUFF WITH CONTEXT
    }
}

Et je l'injecter dans mon BaseActivity comme:

public class BaseActivity extends AppCompatActivity {

    @Inject
    AuthController authController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        BaseActivityComponent component = DaggerBaseActivityComponent.builder()
            .contextModule(new ContextModule(this))
            .build();

        component.injectBaseActivity(this);

        authController.auth();

    }
}

Maintenant, ma question est, comment poignard sait que mon AuthControllers est une dépendance de BaseActivity? Juste en déclarant

@Inject
AuthController authController;

c'est que la même chose que si j'ai créé un ControllerModule comme:

@Module(includes = ContextModule.class)
public class ControllerModule {

    @Provides
    AuthController authController(Context context) {
        return new AuthController(context);
    }

}

Et puis, dans ma BaseActivityComponent je voudrais ajouter mon action authcontroller de lecture et de changer ma dépendance module de ControllersModule:

@BaseActivityScope
@Component(modules = ControllersModule.class)
public interface BaseActivityComponent {

    void injectBaseActivity(BaseActivity baseActivity);

    AuthController getAuthController();
}

Quand je l'appelle injectBaseActivity(ce), il "raconte" la dague que tous @Inject annotations sont des dépendances de ma classe, et puis il les chercheurs pour mon projet @Inject annoté constructeurs qui correspond à ce type?

J'ai pensé qu'une bonne chose à propos de Poignard 2 est que le Module de fichiers pourrait être utilisé comme une "documentation" de mes dépendances trois. Mais si seulement ajouter @Inject dans tous les constructeurs que j'ai le contrôle, ne pourrait-il pas avoir un peu de confusion à l'avenir, car vous ne savez pas ce qui dépend en réalité de quoi? (Je veux dire, vous savez de quoi dépend ce que l', il vous suffit de parcourir un grand nombre de fichiers pour vraiment savoir)

Est-il de meilleures pratiques lors de l'utilisation de @Inject annotations dans les constructeurs ou quand ajouter de l' @Fournit la méthode dans les fichiers de Modules? Je reçois à l'aide de @Inject dans le constructeur je n'ai pas besoin de modifier le constructeur de la définition dans mon fichier de Module, mais est-il un inconvénient?

Merci.

38voto

David Medenjak Points 4553

Quand je l'appelle injectBaseActivity(ce), il "raconte" la dague que tous @Inject annotations sont des dépendances de ma classe, et puis, il cherche pour mon projet @Inject annoté constructeurs qui correspond à ce type?

Exactement. Mais cela ne se fait pas lorsque vous appelez injectBaseActivity, mais tout cela se passe au cours de la compilation. C'est une façon d' annotation processing (un autre fait usage de la réflexion à l'exécution).

Lorsque vous générez votre projet le poignard-annotation-processeur de l'inclure (en tant que dépendance)dans votre construction.gradle fichier est appelé avec une liste de tous vos champs, des cours, etc annoté par l' @Inject d'annotation et construit un graphe de dépendance avec elle. Ensuite, il résout le graphique, génération de code source qui fournit toutes les dépendances, pour les points sur le graphique.

injectBaseActivity juste exécute le code qui a été généré à l'avant, et affecte toutes les dépendances de votre objet. Il est bon de code source, qui vous permet de lire, et de débogage.

La raison que c'est une étape de compilation—simplement—est de la performance et de la validation. (par exemple, Si vous avez quelques cycle de dépendance, vous obtiendrez une erreur de compilation)


comment poignard sait que mon AuthControllers est une dépendance de BaseActivity?

@Inject
AuthController authController;

En annotant le champ @Inject dague sait que vous voulez un AuthController. So far So good. Maintenant poignard va chercher un moyen de fournir le contrôleur, à la recherche d'elle au sein de la composante, les composants de dépendances, et les composants des modules. Il permettra également de voir si la classe peut être fourni, sur son propre, parce qu'il sait à propos de son constructeur.

Comment poignard savoir sur les objets constructeur si vous n'avez pas l'inclure dans n'importe quel module?

@Inject
public AuthController(Context context) { /**/ }

En annotant le constructeur avec vous injectez dit aussi de la dague qu'il y a une classe appelée AuthController et vous avez besoin d'un contexte pour être instancié. C'est fondamentalement le même que l'ajout de votre module.

Un module @Provides méthode doit être utilisée si vous n'avez pas le code source, il suffit d'ajouter le @Inject d'annotation pour le constructeur, ou si l'objet a besoin de plus d'initialisation. Ou dans ton cas...

[...]le Module de fichiers pourrait être utilisé comme une "documentation" de mes dépendances de l'arbre [...]

Oui, bien sûr, vous pourriez le faire. Mais à mesure que votre projet grandit, vous aurez à maintenir beaucoup de code inutile, puisque la même chose pourrait être fait avec un simple annotation sur le constructeur.

Est-il de meilleures pratiques lors de l'utilisation de @Inject annotations dans les constructeurs ou quand ajouter de l' @Fournit la méthode dans les fichiers de Modules?

Si vous souhaitez fournir des versions différentes pour un contexte différent (par exemple, la mise en œuvre d'une interface de 2 façons différentes), il est également l' @Binds d'annotation qui raconte la dague à la classe à laquelle vous souhaitez assurer la mise en œuvre.

Autre que cela, je crois que vous devriez toujours utiliser constructeur d'injection lorsque cela est possible. Si quelque chose change, vous n'avez pas à toucher d'autres parties de votre code, et il est juste moins de code que vous écrivez, et donc moins d'endroits où vous pourriez inclure un bug.

Aussi Poignard et d'optimiser beaucoup en savoir plus, et si vous mettez en œuvre du code superflu, il devra travailler avec le traitement vous a présenté


Bien sûr, à la fin c'est tout jusqu'à ce que vous pensez est le meilleur. Après tout, c'est vous qui doit travailler avec votre code ;)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X