代码之家  ›  专栏  ›  技术社区  ›  E. Fernandes

如何在给定场景中使用Dagger2实现依赖注入?(管理Dagger2上的注入层次结构)

  •  1
  • E. Fernandes  · 技术社区  · 10 年前

    假设我有以下类:

    class Foo {}
    
    class Bar {
        Foo mFoo = new Foo();
    }
    
    class MyActivity extends AppCompatActivity {
         Bar mBar = new Bar();    
    
        @Override
        protected void onCreate (Bundle savedInstance) {
            super(savedInstance);
        }    
    }
    

    从上面的代码可以看出,MyActivity依赖于Bar,Bar依赖于Foo。使用Dagger2实现依赖注入的正确方法是什么?


    我的方法是。。。

    到目前为止,我处理这类操作系统场景的方式是:

    @Singleton
    @Component(
            modules = {
                    MainModule.class,
            })
    public interface MainComponent {
        void inject(MyActivity myActivity);
    
        void inject(Bar bar);
    }
    
    @Module
    class MainModule {
        @Provides
        @Singleton
        Foo provideFoo() {
            return new Foo();
        }
    
        @Provides
        @Singleton
        Bar provideBar() {
            return new Bar();
        }
    }
    

    注射

    class Bar {
        @Inject Foo mFoo;
    
        Bar() {inject(this);}        
    }
    
    class MyActivity extends AppCompatActivity {
        @Inject Bar mBar;
    
        @Override
        protected void onCreate (Bundle savedInstance) {
            super(savedInstance);
            inject(this);
        }    
    }
    

    问题是,根据 this 答:它不应该这样工作, Bar 不应该打电话 inject 并且 Foo 作为参数传递。但是,如果我需要 福 在我项目的其他部分?我应该如何使用Dagger2来实现给定场景?

    2 回复  |  直到 9 年前
        1
  •  1
  •   David Rawson maruti060385    10 年前

    如果更改的构造函数的签名 Bar 为了实现以下目的,您应该实现您想要的效果(构造函数注入)。

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

    然后,您只需要指定 酒吧 在提供程序中,将其作为方法参数写入,如下所示:

    @Provides Bar provideBar(Foo foo)
    

    自从 Foo 和 酒吧 已知的刺穿 @Provide 方法,dagger将自动创建 福 获得 酒吧 像这样的构造函数注入还有一个额外的优势,即使代码易于进行单元测试。在测试中,您可以将 福 福 并测试 福 在…上 酒吧 .

    只有当您无法访问构造函数时(如在Android中),属性注入才是最好的 Activity 和 Service ). 对于其他依赖项,最好使用构造函数注入。

        2
  •  1
  •   codeprogression    10 年前

    您不需要使用模块来提供普通类。您可以直接注释这些类。要始终将Foo作为单例提供,可以对类本身进行注释。

    @Singleton
    @Component
    public interface MainComponent {
      void inject(MyActivity myActivity);
    }
    
    @Singleton
    public class Foo {
    
      @Inject
      public Foo(){}
    }
    
    @Singleton
    public class Bar {
    
      private final Foo foo;
    
      @Inject
      public Bar(final Foo foo){
        this.foo = foo;
      }
    }
    

    当您需要构建/配置实例或提供接口的实现时,需要模块。例如:

    @Module
    class MainModule {
      @Singleton
      @Provides
      Gson gson() {
        return new GsonBuilder.create();
      }
    
      @Singleton
      @Provides
      IBar bar(Bar bar){
        return bar;
      }
    }
    
    // You can also provide an interface with the @Binds attribute instead
    // of using the traditional @Provides annotation
    @Module
    abstract class MainBindsModule {
      @Singleton
      @Binds
      abstract IBar bar(Bar bar);
    }