dagger2 "cannot be provided without an @Inject constructor..."报错的解决

dagger2作为google出的依赖注入框架,在编译时生成依赖注入代码,较square的dagger在运行期反射获取注解内容在运行效率上有了较大的提升。dagger2相对而言学习成本较高,但在解耦较高尤其与mvp的结合使用,还是给项目带来很大的好处。相信有很多的开发者都蠢蠢欲动。关于dagger2原理介绍的文章也有很多,本文主要介绍一下在使用过程中比较常见的一个错误,希望能够帮助大家从错误中更深刻掌握dagger2的一些原理。

一、先看错误:

com.example.zengxianghui900.dagger2application.compoment/Users/zengxianghui900/Downloads/Dagger2Application/app/src/main/java/com/example/zengxianghui900/dagger2application/compoment/MainActivityCompoment.java:14:

Error:(14, 10) 错误: com.example.zengxianghui900.dagger2application.presenter.Register cannot be provided without an @Inject constructor or from an @Provides-annotated method.com.example.zengxianghui900.dagger2application.MainActivity.mPresenter[injected field of type:com.example.zengxianghui900.dagger2application.presenter.MainActivityPresenter mPresenter]com.example.zengxianghui900.dagger2application.module.MainActivityModule.provideMainActivityPresenter(com.example.zengxianghui900.dagger2application.presenter.Register register)[parameter: com.example.zengxianghui900.dagger2application.presenter.Register register]

在它上面还有一个错误(如下):

Error:(9, 64) 错误: 找不到符号
符号:   类 DaggerMainActivityCompoment
位置: 程序包 com.example.zengxianghui900.dagger2application.compoment

二、分析错误

主要看这句:Register cannot be provided without an @Inject constructor or from an @Provides-annotated method,意思是说Register这个类对象不能通过带@Inject的构造函数或带@provieds 注解的方法中获得,所以会报错。

为什么呢?

看报错指向,其指向的是:MainActivityCompoment

/**
 * Created by zengxianghui900 on 17/4/24.
 * MainActivityCompoment
 */

@Component(modules = MainActivityModule.class)
public interface MainActivityCompoment {
    void injectMainActivity(MainActivity mainActivity);		//指向这句报错
}
其实际指向的是MainActivityModule

/**
 * Created by zengxianghui900 on 17/4/24.
 * MainActivityModule
 */
@Module
public class MainActivityModule {

    @Provides
    MainActivityPresenter provideMainActivityPresenter(Register register) {	//实际指向这句,没法获得参数register对象
        return new MainActivityPresenter(register);
    }

}

再看一下Regist类和MainActivityPresenter里面的内容,很简单:

/**
 * Created by zengxianghui900 on 17/4/25.
 *
 */
public class Register {

    private static final String TAG ="Register";
    public void toast() {
        Log.e(TAG, "toast: 注册成功了。。。");
    }
}
/**
 * Created by zengxianghui900 on 17/4/24.
 */
public class MainActivityPresenter {
    private Register mRegister;
    public MainActivityPresenter(Register register) {
        this.mRegister = register;
    }

    //定义一个方法弹一个土司
    public void showToast() {
        mRegister.toast();
    }
}

三、解决错误

既然都知道错误产生的原因了,那接下来看一下怎么解决,有两种方案:

第一种方案:

MainActivityModule中通过@Provides提供Register实例对象,如下:

/**
 * Created by zengxianghui900 on 17/4/24.
 * MainActivityModule
 */
@Module
public class MainActivityModule {
    //添加提供Register实例对象的方法
    @Provides
    Register provideRegister() {    
        return new Register();
    }

    @Provides
    MainActivityPresenter provideMainActivityPresenter(Register register) {
        return new MainActivityPresenter(register);
    }

}

第二种方案:

在Register类中能过@Inject注解其构造函数,如下:

/**
 * Created by zengxianghui900 on 17/4/25.
 *
 */
public class Register {

    private static final String TAG ="Register";
    //用Inject标注构造函数
    @Inject
    public Register(){

    }
    public void toast() {
        Log.e(TAG, "toast: 注册成功了。。。");
    }
}

以下任何一种方案都能解决这个问题,那么原理呢?

逻辑如下:

1. provideMainActivityPresenter方法会先去判断该module中是否有提供Register实例对象的方法,有则成功返回结束。

2. 如果没有,会再去Register类中查找是否有带@Inject标记的构造方法,如果有则成功返回结束。

3.如果也没有,那么就会报这个错误了。
















你可能感兴趣的:(bug大全)