我一直在尝试实施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中不起作用。请有人解释一下。
答案 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
带注释的构造函数。你应该取消对构造函数的注释,因为这是你的情况。