7

我有一个简单的 Dagger 2 测试设置,基于http://konmik.github.io/snorkeling-with-dagger-2.html。它注入了一个输出所有首选项的 PreferenceLogger。在注入的类中,我可以@Inject 更多的类。

public class MainActivity extends Activity {
    @Inject PreferencesLogger logger;
    @Inject MainPresenter presenter;

    @Override protected void onCreate(Bundle savedInstanceState) {
    MyApplication.getComponent().inject(this);
    presenter.doStuff();
        logger.log(this);
    }
}


public class PreferencesLogger {

    @Inject OkHttpClient client;
    @Inject public PreferencesLogger() {}

    public void log(Contect context) {
    // this.client is available
    }
}

当我运行它时,设置了记录器,并且在 PreferencesLogger.log 中正确设置了 OkHttpClient。所以这个例子按预期工作。现在我正在尝试建立一个 MVP 结构。有一个带有实现的 MainPresenter 接口。在 MainActivity 我设置了一个:

@Inject MainPresenter presenter;

所以我可以用另一种(调试或测试)实现来切换这个 MainPresenter。当然,现在我需要一个 Module 来指定我想要使用的实现。

public interface MainPresenter {
    void doStuff();
}

public class MainPresenterImpl implements MainPresenter {

    @Inject OkHttpClient client;

    public MainPresenterImpl() {}

    @Override public void doStuff() {
    // this.client is not available    
    }
}


@Module public class MainActivityModule {
    @Provides MainPresenter provideMainPresenter() {
        return new MainPresenterImpl();
    }
}

现在出现了一个问题,即不再注入 OkHttpClient。当然,我可以更改模块以接受参数 OkHttpClient,但我认为这不是建议的方法。MainPresenterImpl 没有正确注入有什么原因吗?

4

2 回答 2

5

您可以注入您的MainPresenterImplusing 构造函数注入。

/* unscoped */
public class MainPresenterImpl implements MainPresenter {

    @Inject 
    OkHttpClient client;

    @Inject
    public MainPresenterImpl() {
    }

    @Override public void doStuff() {
       // this.client is now available! :)
    }
}


@Module 
public class AppModule {
    private MyApplication application;

    public AppModule(MyApplication application) {
        this.application = application;
    }

    @Provides
    /* unscoped */ 
    public MyApplication application() {
        return application;
    }
}

@Module 
public abstract class MainActivityModule {
    @Binds public abstract MainPresenter mainPresenter(MainPresenterImpl mainPresenterImpl);
}
于 2015-05-31T09:02:47.637 回答
4

与构造函数注入不同,方法中@Inject构造的依赖项的注释字段@Provides不能自动注入。能够注入字段需要一个在其模块中提供字段类型的组件,并且在提供程序方法本身中,这样的实现是不可用的。

当该presenter字段被注入时MainActivity,所发生的一切就是调用提供者方法并将presenter其设置为它的返回值。在您的示例中,无参数构造函数不进行初始化,提供者方法也不进行初始化,因此不会进行初始化。

然而,提供者方法确实可以通过其参数访问模块中提供的其他类型的实例。我认为在提供者方法中使用参数实际上是“注入”所提供类型的依赖项的建议(甚至是唯一)方法,因为它明确地将它们指示为模块中的依赖项,这允许 Dagger 在编译时抛出错误- 时间如果他们不能满足。

它当前没有抛出错误的原因是因为如果不是某个注入目标,它的依赖关系MainPresenterImpl 就可以得到满足。Dagger 不能为接口类型创建成员注入方法,因为作为一个接口,它不能有可注入的字段,并且它不会自动注入实现类型的字段,因为它只是提供任何提供者方法返回。OkHttpClientMainPresenterImplMainPresenter

于 2015-05-06T06:04:39.753 回答