我在
Android项目中使用
Dagger依赖注入,可以编译和构建应用程序.对象图看起来是正确的和工作的,但是当我添加匕首编译器作为依赖,以便在编译时获取错误,它报告一些奇怪的错误:
- [ERROR] error: No binding for com.squareup.tape.TaskQueue<com.atami \
- .mgodroid.io.NodeIndexTask> required by com.atami \
- .mgodroid.ui.NodeIndexListFragment for com.atami.mgodroid \
- .modules.OttoModule
- [ERROR] error: No binding for com.squareup.tape.TaskQueue<com.atami \
- .mgodroid.io.NodeTask> required by com.atami \
- .mgodroid.ui.NodeFragment for com.atami.mgodroid.modules.OttoModule
- [ERROR] error: No injectable members on com.squareup.otto.Bus. Do you want
- to add an injectable constructor? required by com.atami. \
- mgodroid.io.NodeIndexTaskService for
- com.atami.mgodroid.modules.TaskQueueModule
Otto错误看起来像Eric Burke在他的Android App Anatomy演示文稿中提到的没有一个@Provides注释,但是你可以在下面看到.
我的Otto和TaskQueue模块如下:
- @Module(
- entryPoints = {
- MGoBlogActivity.class,NodeIndexListFragment.class,NodeFragment.class,NodeActivity.class,NodeCommentFragment.class,NodeIndexTaskService.class,NodeTaskService.class
- }
- )
- public class OttoModule {
- @Provides
- @Singleton
- Bus provideBus() {
- return new AsyncBus();
- }
- /**
- * Otto EventBus that posts all events on the Android main thread
- */
- private class AsyncBus extends Bus {
- private final Handler mainThread = new Handler(Looper.getMainLooper());
- @Override
- public void post(final Object event) {
- mainThread.post(new Runnable() {
- @Override
- public void run() {
- AsyncBus.super.post(event);
- }
- });
- }
- }
- }
…
- @Module(
- entryPoints = {
- NodeIndexListFragment.class,NodeTaskService.class
- }
- )
- public class TaskQueueModule {
- private final Context appContext;
- public TaskQueueModule(Context appContext) {
- this.appContext = appContext;
- }
- public static class IOTaskInjector<T extends Task>
- implements TaskInjector<T> {
- Context context;
- /**
- * Injects Dagger dependencies into Tasks added to TaskQueues
- *
- * @param context the application Context
- */
- public IOTaskInjector(Context context) {
- this.context = context;
- }
- @Override
- public void injectMembers(T task) {
- ((MGoBlogApplication) context.getApplicationContext())
- .objectGraph().inject(task);
- }
- }
- public static class ServiceStarter<T extends Task>
- implements ObjectQueue.Listener<T> {
- Context context;
- Class<? extends Service> service;
- /**
- * Starts the provided service when a Task is added to the queue
- *
- * @param context the application Context
- * @param service the Service to start
- */
- public ServiceStarter(Context context,Class<? extends Service> service) {
- this.context = context;
- this.service = service;
- }
- @Override
- public void onAdd(ObjectQueue<T> queue,T entry) {
- context.startService(new Intent(context,service));
- }
- @Override
- public void onRemove(ObjectQueue<T> queue) {
- }
- }
- @Provides
- @Singleton
- TaskQueue<NodeIndexTask> provideNodeIndexTaskQueue() {
- ObjectQueue<NodeIndexTask> delegate =
- new InMemoryObjectQueue<NodeIndexTask>();
- TaskQueue<NodeIndexTask> queue = new TaskQueue<NodeIndexTask>(
- delegate,new IOTaskInjector<NodeIndexTask>(appContext));
- queue.setListener(new ServiceStarter<NodeIndexTask>(
- appContext,NodeIndexTaskService.class));
- return queue;
- }
- @Provides
- @Singleton
- TaskQueue<NodeTask> provideNodeTaskQueue() {
- ObjectQueue<NodeTask> delegate =
- new InMemoryObjectQueue<NodeTask>();
- TaskQueue<NodeTask> queue = new TaskQueue<NodeTask>(
- delegate,new IOTaskInjector<NodeTask>(appContext));
- queue.setListener(new ServiceStarter<NodeTask>(
- appContext,NodeTaskService.class));
- return queue;
- }
- }
…
- /**
- * Module that includes all of the app's modules. Used by Dagger
- * for compile time validation of injections and modules.
- */
- @Module(
- includes = {
- MGoBlogAPIModule.class,OttoModule.class,TaskQueueModule.class
- }
- )
- public class MGoBlogAppModule {
- }
解决方法
匕首的全图分析从一个完整的模块中工作.即@Module(complete = true),这是默认值.因为它是默认值,默认情况下,匕首将假定所有绑定都可以从该模块或其明确包含的模块中获得.
在这种情况下,您已经给出了两个声明完整的模块,但是Dagger无法在编译时将这些模块绑定在一起,而无需额外的信号.简而言之,没有OttoModule知道TaskQueueModule,编译器将尝试分析OttoModule的声明完整性,并且失败,因为它现在不关于TaskQueueModule.
修改OttoModule的注释:
- @Module(
- includes = TaskQueueModule.class,entryPoints = {
- MGoBlogActivity.class,NodeTaskService.class
- }
- )
然后Dagger会知道,为了完成OttoModule,它将其他模块作为其完整定义的一部分.
注意:匕首编译器无法检测到TaskQueueModule在类路径上,只是“知道”开发人员打算将其与OttoModule一起使用,而没有附加信号.例如,您可能有几个模块可以定义任务队列,哪些模块可以选择?声明必须明确.