2015-04-23 14 views
7

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

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无法正确注入的原因是什么?

+0

我在这里提出一个相关的问题:http://stackoverflow.com/questions/30555285/dagger2-injecting-implementation-classes-with-component – EpicPandaForce

+0

看看这篇文章和示例项目,该项目可能会有所帮助: https://medium.com/@m_mirhoseini/yet-another-mvp-article-part-1-lets-get-to-know-the-project-d3fd553b3e21#.6y9ze7e55 –

回答

4

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

presenter字段在MainActivity注入,所发生的一切是提供方法被调用,presenter设置为它的返回值。在你的例子中,无参数构造函数没有进行初始化,提供者方法也没有,因此不进行初始化。

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

它之所以目前不抛出一个错误是因为MainPresenterImpl可能得到它OkHttpClient依赖性满意,如果MainPresenterImpl,而不是MainPresenter某处用于注射的目标。 Dagger无法为接口类型创建成员注入方法,因为作为接口,它不能注入字段,也不会自动注入实现类型的字段,因为它只是提供任何提供者方法回报。

4

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