使用注释处理器生成Dagger组件(Generate Dagger components using Annotation Processor)

我正在开发一个遵循MVP架构模式的Android应用程序。 在我的所有片段中,我正在注入一个演示者。 因此我的片段(视图)需要有一个Component,我在其中声明了注入。 例如:

@ActivityScope @Component( dependencies = AppComponent.class, modules = { PresenterModule.class, InteractorModule.class } ) public interface ViewInjectorComponent { void inject(SelectEventOccurrenceFragment fragment); void inject(CreateOpponentFragment fragment); void inject(SelectOpponentFragment fragment); void inject(TeammatesInvitedFragment fragment); ... }

我添加到我的应用程序(片段)中的每个新视图都需要在此处声明其条目。 我想知道是否可以使用某种注释处理器自动生成此代码。 该应用程序已经有几个片段,这个组件文件很容易有300多个条目。 如果我可以这样做,那真是太棒了:

@Injectable public class MyNewFragment implements MyNewView { ... }

然后在ViewInjectorComponent文件中自动生成条目。 这是可能的? 我应该在哪里看?

I'm working on an Android App which follows the MVP architecture pattern. In all my fragments I'm injecting a Presenter. Therefore my Fragments (Views) need to have a Component in which I declare the injects. For example:

@ActivityScope @Component( dependencies = AppComponent.class, modules = { PresenterModule.class, InteractorModule.class } ) public interface ViewInjectorComponent { void inject(SelectEventOccurrenceFragment fragment); void inject(CreateOpponentFragment fragment); void inject(SelectOpponentFragment fragment); void inject(TeammatesInvitedFragment fragment); ... }

Every new View that I add into my App (Fragment) needs to have its entry declared here. I was wondering if It's possible to generate this code automatically with some kind of annotation processor. The App has already several fragments, this component file has easily more than 300 entries. It'd be awesome if I could do something like:

@Injectable public class MyNewFragment implements MyNewView { ... }

And then automatically generate the entry in the ViewInjectorComponent file. It's possible? Where should I look at?

最满意答案

您遇到的情况可能是以不寻常的方式组织模块和组件的结果。 特别是,横向分组(一个Component注入所有Presenters)而不是垂直分组(一个组件注入与SelectOpponentActivity相关的功能)是有问题的。

一个很好的例子是Google Android架构蓝图GitHub repo 。 如果您仔细阅读那里的代码,您将看到他们在一个Java包中组织了与Tasks相关的功能以及单独的Component,Module,Presenter等。这样可以限制类的构造函数的可访问性。包含在其中并实现有效的Java项目13: 最小化类和成员的可访问性。

同样,您已将所有模块组合到一个Presenter模块和一个Interactor模块中。 Dagger 2官方文档的建议是首先组织模块以实现可测试性 ,然后沿着功能线。 同样,您可以参考Blueprint示例了解如何执行此操作。

最后,请注意,使用大多数DI框架(如Dagger 2)时不可避免地会遇到一些样板。从某种意义上说,您正在交换一个更大的问题(“我如何处理所有这些构造函数?”),而且问题要小得多且易于管理(“我如何分组我的组件”等)。

更新有一个名为Auto Dagger2的库可以为您生成组件。 看到这个Github回购 。 以下是注释的示例:

@AutoComponent @Singleton public class ExampleApplication extends Application { }

其中生成以下代码:

@Component @Singleton public interface ExampleApplicationComponent { }

如果您对代码生成工具感兴趣,请查看Google Auto 。

The situation you are experiencing may be a consequence of organising your Modules and Components in an unusual way. In particular, grouping laterally (one Component injects all the Presenters) rather than vertically (one component injects the functionality related to SelectOpponentActivity) is problematic.

A good example to follow is in the Google Android Architecture Blueprints GitHub repo. If you peruse the code there, you will see that they have organised functionality related to Tasks inside one Java package together with a separate Component, Module, Presenter etc. This has the nice advantage of being able to restrict accessibility of the constructors of the classes contained therein and fulfilling Effective Java Item 13: Minimize the accesibility of classes and members.

Likewise, you've grouped all your modules together into a Presenter Module and an Interactor Module. The advice from the Dagger 2 official documentation is to organise Modules first for testability and then along functional lines. Again, you can refer to the Blueprint example for how to do this.

Finally, note that there is unavoidably some boilerplate involved in using most DI frameworks like Dagger 2. In a sense, you are exchanging a bigger problem ("how do I deal with all of these constructors?") with much smaller and more manageable problems ("how do I group my Components" etc.).

Update There is a library called Auto Dagger2 that can generate components for you. See this Github repo. Here is an example of an annotation:

@AutoComponent @Singleton public class ExampleApplication extends Application { }

Which generates the following code:

@Component @Singleton public interface ExampleApplicationComponent { }

Also check out Google Auto if you are interested in code generation tools.

更多推荐