Dagger:在提供的pojo上注入字段

 小白菜 发布于 2022-12-13 15:44

目前使用dagger进行测试,我想要做的是实例化并注入不同的Bar实现.如何在提供的字段中注入字段?例如:

模块:

@Module(
        injects = {
                Main.class
        },
        complete = false,
        library = true
)
public class ExampleTestModule {
    @Provides
    public Foo providesFoo() {
        return new Foo();
    }
    @Provides
    public Bar providesBar(BarImpl impl) {
        // return new BarImpl(); // null
        return impl;
    }
}

主要:

public class Main {
    @Inject
    Foo foo;
}

富:

public class Foo {
    @Inject
    Bar bar;
}

酒吧:

public interface Bar {

}

BarImpl

public class BarImpl implements Bar {
}

测试用例:

public class ApplicationTest extends ApplicationTestCase {
    public ApplicationTest() {
        super(Application.class);
    }


    public void testFoo() {
        Main main = new Main();
        ObjectGraph.create(new ExampleTestModule()).inject(main);
        assertNotNull(main.foo);
    }

    public void testFooBar() {
        Main main = new Main();
        ObjectGraph.create(new ExampleTestModule()).inject(main);
        assertNotNull(main.foo.bar);
    }
}

Main.Foo不为null,但Main.Foo.Bar为null.

1 个回答
  • 你永远不会注入barfoo.

    ObjectGraph.create(new ExampleTestModule()).inject(main);
    

    该行仅查看main其注释的字段@Inject,并注入它们.没有递归行为.


    解决问题

    我们一步一步走吧:

    你提供complete = falselibrary = true在你的Module.你应该只在必要时才使用它们.当出现问题时,Dagger会给你警告,这些属性会压制这些警告.例如,删除它们会在编译时引发以下警告:

    Error:(11, 8) error: No injectable members on BarImpl. Do you want to add an injectable constructor? required by providesBar(BarImpl) for ExampleTestModule.
    

    让我们添加一个空的可注入构造函数BarImpl,因为它建议:

    public class BarImpl implements Bar {
        @Inject
        BarImpl(){
        }
    }
    

    编译会给出一个新错误:

    Error:(11, 8) error: Graph validation failed: You have these unused @Provider methods:
    1. ExampleTestModule.providesBar()
    Set library=true in your module to disable this check.
    

    显然,providesBar()从未使用过.这意味着,永远不会注入该bar领域Foo.你可以做两件事:

      bar手动注入:

      ObjectGraph graph = ObjectGraph.create(new ExampleTestModule());
      graph.inject(main);
      graph.inject(main.foo);
      

      使用可注射构造函数(首选选项):

      public class Foo {
          Bar bar;
      
          @Inject
          Foo(Bar bar){
              this.bar = bar;
          }
      }
      

    使用injectable构造函数,您现在将遇到编译错误providesFoo(),因为您没有BarFoo构造函数中提供实例.关于Dagger的好处是,您可以安全地完全删除此方法.由于它Foo是注释的@Injectable,它需要注入一个Foo实例,它使用这个构造函数.当它使用这个构造函数时,它注意到它需要一个Bar实例,并注入它.

    最后,我们可以@InjectFoo字段中删除注释Main,并创建一个可注入的构造函数.使用ObjectGraph.get(Class<?>)我们可以检索完全实例化的Main实例.


    结果

    最终结果应如下所示:

    模块:

    @Module(
            injects = Main.class
    )
    public class ExampleTestModule {
        @Provides
        public Bar providesBar(BarImpl impl) {
            return impl;
        }
    }
    

    主要:

    public class Main {
        Foo foo;
    
        @Inject
        Main(Foo foo) {
            this.foo = foo;
        }
    }
    

    富:

    public class Foo {
        Bar bar;
    
        @Inject
        Foo(Bar bar){
            this.bar = bar;
        }
    }
    

    酒吧:

    public interface Bar {
    }
    

    BarImpl:

    public class BarImpl implements Bar {
        @Inject
        BarImpl(){
        }
    }
    

    ApplicationTest:

    public class ApplicationTest extends ApplicationTestCase<Application> {
    
        public ApplicationTest() {
            super(Application.class);
        }
    
    
        public void testFoo() {
            Main main = ObjectGraph.create(new ExampleTestModule()).get(Main.class);
            assertNotNull(main.foo);
        }
    
        public void testFooBar() {
            Main main = ObjectGraph.create(new ExampleTestModule()).get(Main.class);
            assertNotNull(main.foo.bar);
        }
    }
    

    结论

    从结果中,我们可以得出一些结论:

    不要只添加library = truecomplete = false模块.只有在使用多个复杂模块时才需要这样做.

    尝试使用注射构造函数.这就是Dagger所建造的,并且效果最佳.额外的好处是,您现在可以拥有自己的领域private,就像它们应该的那样.

    当使用可注入的构造函数时,实际上只需要providesXXX在注入接口实例时创建方法,就像我们使用BarBarImpl.因为,嘿,这正是Dependency Injection的用途,对吧?

    2022-12-13 15:50 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有