匕首找不到注射成员模块找不到、匕首、模块、成员

2023-09-05 07:55:11 作者:空白的心再也没有颜色≈

我使用在Android项目匕首的依赖注入,而且可以编译和构建应用程序的罚款。对象图似乎是正确的工作,但是当我加入匕首编译器的依赖,以得到错误在编译时,它报告了一些奇怪的错误:

  [错误]错误:不com.squareup.tape.TaskQueue&LT约束力; com.atami \
    .mgodroid.io.NodeIndexTask>通过com.atami \要求
    .mgodroid.ui.NodeIndexListFragment的com.atami.mgodroid \
    .modules.OttoModule
[错误]错误:不com.squareup.tape.TaskQueue&LT约束力; com.atami \
    .mgodroid.io.NodeTask>通过com.atami \要求
    .mgodroid.ui.NodeFragment的com.atami.mgodroid.modules.OttoModule
[错误]错误:com.squareup.otto.Bus没有注射的成员。你想要吗
     添加可注射的构造函数?通过com.atami要求。 \
     mgodroid.io.NodeIndexTaskService为
     com.atami.mgodroid.modules.TaskQueueModule
 

奥托错误看起来像一个埃里克·伯克提到他的 Android应用解剖 presentation大约没有一个 @Provides 注释,但你可以看到下面我做的。

我的奥托和任务队列模块如下:

  @Module(
        入口点= {
                MGoBlogActivity.class,
                NodeIndexListFragment.class,
                NodeFragment.class,
                NodeActivity.class,
                NodeCommentFragment.class,
                NodeIndexTaskService.class,
                NodeTaskService.class
        }
)
公共类OttoModule {

    @Provides
    @Singleton
    巴士p​​rovideBus(){
        返回新AsyncBus();
    }

    / **
     *奥托EventBus的员额的所有事件在Android主线程
     * /
    私有类AsyncBus扩展总线{
        私人最终处理程序mainThread =新的处理程序(Looper.getMainLooper());

        @覆盖
        公共无效后(最终目标事件){
            mainThread.post(新的Runnable(){
                @覆盖
                公共无效的run(){
                    AsyncBus.super.post(事件);
                }
            });
        }
    }
}
 

...

  @Module(
    入口点= {
        NodeIndexListFragment.class,
        NodeFragment.class,
        NodeIndexTaskService.class,
        NodeTaskService.class
    }
)
公共类TaskQueueModule {

    私人最终语境appContext;

    公共TaskQueueModule(上下文appContext){
        this.appContext = appContext;
    }

    公共静态类IOTaskInjector<吨延长任务>
        实现TaskInjector< T> {

        上下文语境;

        / **
         *注入匕首依赖关系加入到任务队列任务
         *
         * @参数范围内的应用程序上下文
         * /
        公共IOTaskInjector(上下文的背景下){
            this.context =背景;
        }

        @覆盖
        公共无效injectMembers(T任务){
            ((MGoBlogApplication)context.getApplicationContext())
                。.objectGraph()注入(任务);
        }
    }

    公共静态类ServiceStarter<吨延长任务>
        实现ObjectQueue.Listener< T> {

        上下文语境;
        类和LT ;?延伸服务和GT;服务;

        / **
         *时启动一个任务被添加到队列中提供的服务
         *
         * @参数范围内的应用程序上下文
         *参数服务的服务启动
         * /
        公共ServiceStarter(上下文的背景下,
                              类和LT ;?延伸服务和GT;服务) {
            this.context =背景;
            this.service =服务;
        }

        @覆盖
        公共无效onAdd(ObjectQueue< T>队列,T进入){
            context.startService(新意图(背景下,服务));

        }

        @覆盖
        公共无效onRemove(ObjectQueue< T>队列){
        }
    }


    @Provides
    @Singleton
    任务队列< NodeIndexTask> provideNodeIndexTaskQueue(){
        ObjectQueue< NodeIndexTask>委托=
            新InMemoryObjectQueue< NodeIndexTask>();
        任务队列< NodeIndexTask>队列=新任务队列< NodeIndexTask>(
            代表,新IOTaskInjector< NodeIndexTask>(appContext));
        queue.setListener(新ServiceStarter< NodeIndexTask>(
            appContext,NodeIndexTaskService.class));
        返回队列;
    }

    @Provides
    @Singleton
    任务队列< NodeTask> provideNodeTaskQueue(){
        ObjectQueue< NodeTask>委托=
            新InMemoryObjectQueue< NodeTask>();
        任务队列< NodeTask>队列=新任务队列< NodeTask>(
            代表,新IOTaskInjector< NodeTask>(appContext));
        queue.setListener(新ServiceStarter< NodeTask>(
            appContext,NodeTaskService.class));
        返回队列;
    }
}
 
我的拨片又找不到了 做个拨片包

...

  / **
 *模块,包括所有的应用程序的模块。用匕首
 *注射和模块的编译时验证。
 * /
@Module(
        包括= {
                MGoBlogAPIModule.class,
                OttoModule.class,
                TaskQueueModule.class
        }
)
公共类MGoBlogAppModule {
}
 

解决方案

匕首的全图表分析从一个完整的模块工作。即@Module(完整= true),这是默认的。因为它是默认的,将匕首在默认情况下,假设所有绑定都可以从该模块或这些模块它明确地包含。

在这种情况下,你已经给你声称是完整的两个模块,但匕首已经没有办法在编译时,不需要额外的信号一起把这些。总之,没有OttoModule寂寂TaskQueueModule,编译器将尝试分析OttoModule其声称完整性和失败,因为它没有现在大约TaskQueueModule。

修改OttoModule的注解这样:

  @Module(
  包括= TaskQueueModule.class,
  入口点= {
    MGoBlogActivity.class,
    NodeFragment.class,
    NodeActivity.class,
    NodeCommentFragment.class,
    NodeIndexTaskService.class,
    NodeTaskService.class
  }
)
 

然后匕首就会知道,OttoModule是完整的,它包括其他模块作为其完整的定义部分。

注意: 的匕首,编译器无法检测到TaskQueueModule是那里的类路径,只是知道,开发商意欲它与OttoModule使用而不这额外的信号。例如,你可能有几个模块,定义任务队列,哪些人会选择它?该声明必须是明确的。

I'm using Dagger for dependency injection in an Android project, and can compile and build the app fine. The object graph appears to be correct and working, but when I add dagger-compiler as a dependency to get errors at compile time, it reports some bizarre errors:

[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

The Otto error looks like the one Eric Burke mentions in his Android App Anatomy presentation about not having a @Provides annotation, but as you can see below I do.

My Otto and TaskQueue modules are as follows:

@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,
        NodeFragment.class,
        NodeIndexTaskService.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 {
}

解决方案

Dagger's full graph analysis works from a complete module. i.e. @Module(complete = true), which is the default. Because it's the default, dagger will, by default, assume that all bindings are available from that module or those modules it includes explicitly.

In this case, you've given two modules that you claim are complete, but Dagger has no way to tie these together at compile time without an additional signal. In short, without OttoModule knowing about TaskQueueModule, the compiler will attempt to analyse OttoModule for its claimed completeness, and fail, because it doesn't now about TaskQueueModule.

Modify OttoModule's annotation as such:

@Module(
  includes = TaskQueueModule.class,
  entryPoints = {
    MGoBlogActivity.class,
    NodeFragment.class,
    NodeActivity.class,
    NodeCommentFragment.class,
    NodeIndexTaskService.class,
    NodeTaskService.class
  }
)

and then Dagger will know that for OttoModule to be complete, it includes the other module as part of its full definition.

Note:dagger-compiler can't detect that TaskQueueModule is there on the class path and just "know" that the developer intended it to be used with OttoModule without that additional signal. For instance, you might have several modules which define task queues and which one would it select? The declaration must be explicit.