微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

android – Dagger无法在模块上找到注入成员

我在 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一起使用,而没有附加信号.例如,您可能有几个模块可以定义任务队列,哪些模块可以选择?声明必须明确.

原文地址:https://www.jb51.cc/android/313345.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐