Dagger 2和接口实现

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。当然,现在我需要一个模块来指定我想要使用的实现。

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不能正确注入?

我在这里问了一个相关的问题:https://dev59.com/NIvda4cB1Zd3GeqPZnQO - EpicPandaForce
请查看以下文章和示例项目,这可能会有所帮助: https://medium.com/@m_mirhoseini/yet-another-mvp-article-part-1-lets-get-to-know-the-project-d3fd553b3e21#.6y9ze7e55 - Mohsen Mirhoseini
2个回答

5
您可以使用构造函数注入来注入您的MainPresenterImpl
/* 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);
}

5
与构造函数注入不同,使用@Provides方法构建的依赖项中的@Inject注释字段不能自动注入。要注入字段,需要一个提供模块类型的组件,在提供程序方法本身中,这样的实现是不可用的。
当在MainActivity中注入presenter字段时,所发生的只是调用了提供程序方法,presenter被设置为其返回值。在您的示例中,无参构造函数不执行任何初始化,提供程序方法也不执行任何初始化,因此不会进行任何初始化。
但是,提供程序方法可以通过其参数访问模块中提供的其他类型的实例。我认为在提供程序方法中使用参数实际上是“注入”提供类型的依赖项的建议方法(甚至是唯一的方法),因为它在模块内明确地将它们标识为依赖项,这允许Dagger在编译时抛出错误,如果无法满足它们。
它目前没有抛出错误的原因是因为如果MainPresenterImpl而不是MainPresenter在某个位置成为注入目标,则MainPresenterImpl可以得到其OkHttpClient依赖项的满足。Dagger 无法为接口类型创建成员注入方法,因为作为接口,它不能具有可注入字段,并且它不会自动注入实现类型的字段,因为它只提供提供程序方法返回的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接