Dagger2 - 项目重建错误 - 现场注入 - Android

时间:2018-01-22 11:46:04

标签: java android dependency-injection dagger-2 constructor-injection

我一直在尝试实施Dagger2。

问题:当我使用构造函数注入时,它工作正常但是当我使用字段注入时,它会抛出如下错误:

Error:(6, 48) error: cannot find symbol class DaggerApplicationComponent
/home/moderator/Downloads/Maulik/Sample Codes/Made/Dagger2Demo/app/src/main/java/com/dagger2demo/dagger2demo/di/component/ApplicationComponent.java
Error:(18, 10) error: com.dagger2demo.dagger2demo.mvp.HomePresenter cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method. This type supports members injection but cannot be implicitly provided.
com.dagger2demo.dagger2demo.mvp.HomePresenter is injected at
com.dagger2demo.dagger2demo.mvp.BaseActivity.homePresenter
com.dagger2demo.dagger2demo.mvp.BaseActivity is injected at
com.dagger2demo.dagger2demo.di.component.ApplicationComponent.inject(baseActivity)
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.

Dagger2 - 我的理解:您必须创建一个Module类,您将在其中创建方法。这些方法将为您提供所需类的相应对象,如Retrofit,ApplicationContext等。您将创建一个组件接口,您将在其中定义注入模块类依赖项的位置。

我正在使用: Retrofit,RxJava - RaxAndroid,Dagger2& MVP。

代码如下:

的build.gradle(APP)

// Retrofit Dependency
compile 'com.squareup.retrofit2:retrofit:2.3.0'

// Gson Converter Factory Dependency
compile 'com.squareup.retrofit2:converter-gson:2.3.0'

// RxJava2 Adapter Dependency for Retrofit2
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

// ButterKnife Dependencies
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

// RxJava & RxAndroid Dependencies
compile group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.1.8'
compile group: 'io.reactivex.rxjava2', name: 'rxandroid', version: '2.0.1'

// Dagger2 Dependency
compile 'com.google.dagger:dagger:2.14.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'

Dagger2DemoApplication.java

    public class Dagger2DemoApplication extends Application {

    private ApplicationComponent mApplicationComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        mApplicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule())
                .build();
    }

    public ApplicationComponent getmApplicationComponent() {
        return mApplicationComponent;
    }
}

ApplicationModule.java

    @Module
public class ApplicationModule {

    @Provides
    @Singleton
    public APIEndPoints provideAPIEndPoints() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://reqres.in/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        APIEndPoints apiEndPoints = retrofit.create(APIEndPoints.class);

        return apiEndPoints;
    }
}

ApplicationComponent.java

    @Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {

    void inject(BaseActivity baseActivity);
}

BaseActivity.java

    public class BaseActivity extends AppCompatActivity {

    // Variables
    public ProgressDialog mProgressDialog;

    @Inject
    HomePresenter homePresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // For Dagger2 i.e Creating instance of all provide methods defined in ApplicationModule
        ((Dagger2DemoApplication) getApplication()).getmApplicationComponent().inject(this);

        setupProgressBar();
    }

    private void setupProgressBar() {
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setTitle(getString(R.string.str_progress_dialog_title));
        mProgressDialog.setMessage(getString(R.string.str_progress_dialog_desc));
        mProgressDialog.setCancelable(false);
    }
}

BaseView.java

    public interface BaseView extends View {

    void handleResponse(Object obj);

    void showMessage(String msg);
}

View.java

    public interface View {

}

BasePresenter.java

public interface BasePresenter {

    void attachView(View view);

    void callAPI();
}

HomePresenter.java

    public class HomePresenter implements BasePresenter {

    private BaseView mBaseView;

    @Inject
    APIEndPoints mApiEndPoints;

    /*@Inject
    public HomePresenter(APIEndPoints apiEndPoints) {
        this.mApiEndPoints = apiEndPoints;
    }*/

    @Override
    public void attachView(View view) {
        mBaseView = (BaseView) view;
    }

    @Override
    public void callAPI() {

        // Actually calling API here with observable object - Start
        Observable<Users> usersObservable = mApiEndPoints.getUsers();

        usersObservable
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(this::onSuccess, this::onError);
        // Actually calling API here with observable object - End
    }

    private void onSuccess(Users users) {
        mBaseView.handleResponse(users);
    }

    private void onError(Throwable throwable) {
        mBaseView.showMessage(throwable.toString());
    }
}

HomeActivity.java

    public class HomeActivity extends BaseActivity implements BaseView {

    // Widgets
    @BindView(R.id.rv_users)
    RecyclerView rv_users;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // For ButterKnife
        ButterKnife.bind(this);

        // Initializing Presenter
        homePresenter.attachView(this);
    }

    public void getDataFromServer(View view) {
        mProgressDialog.show();
        homePresenter.callAPI();
    }

    // BaseView Methods
    @Override
    public void handleResponse(Object obj) {
        Users users;
        if (obj instanceof Users) {
            users = (Users) obj;
            if (users != null) {
                mProgressDialog.dismiss();
                rv_users.setLayoutManager(new LinearLayoutManager(HomeActivity.this));
                rv_users.setAdapter(new RVAdapter(users.getData()));
            }
        }
    }

    @Override
    public void showMessage(String msg) {
        if (msg != null) {
            mProgressDialog.dismiss();
            Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
        }
    }
}

如您所见,我在HomePresenter中评论了构造函数注入。我在那里进行了Field Injection。但是我无法构建项目,因为我收到了如上所述的错误。

任何帮助将不胜感激。如果需要与代码相关的任何其他内容,请告诉我。

提前致谢。

修改 PS:我知道答案,但我无法理解为什么Field Injection即 @Inject     APIEndPoints mApiEndPoints; 在HomePresenter中不起作用。请有人解释一下。

2 个答案:

答案 0 :(得分:1)

  

如您所见,我在HomePresenter中评论了构造函数注入。我在那里进行了Field Injection。

如果您使用构造函数注入,那么Dagger将为您创建对象并了解所有相关内容。

如果您使用字段注入,那么必须创建对象告诉Dagger。

我不明白为什么你更喜欢在这种情况下使用字段注入,但是通过字段注入,你需要在你的一个模块中添加一个@Provides带注释的方法,以便Dagger访问你的演示者。 / p>

您需要在模块中使用Construcotr注入或@Provides带注释的方法,就像错误一样。

答案 1 :(得分:0)

您混淆依赖关系生成器机制和依赖关系消费机制。带注释的字段用于使用依赖项。在你的情况下,@Inject HomePresenter homePresenter告诉Dagger&#34;嘿,我希望你在这里注入一个HomePresenter&#34;。为此,Dagger要么您需要定义@Provides方法,要么让对象构造函数用@Inject注释。

根据经验,始终使用@Inject带注释的构造函数来提供依赖关系。当您提供的对象是:

时,您应该只使用@Provides方法提供程序
  • interface
  • abstract
  • 来自外部库的对象(您无法访问构造函数)
  • 在提供之前需要自定义的对象

在您的情况下,您收到了错误,因为您没有@Provides带注释的方法,也没有@Inject带注释的构造函数。你应该取消对构造函数的注释,因为这是你的情况。