簡體   English   中英

Dagger2-項目重建錯誤-字段注入-Android

[英]Dagger2 - Project Rebuild Error - Field Injection - Android

我一直在嘗試實現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-我的理解:您必須創建一個模塊類,在其中創建方法。 這些方法將為您提供所需類的相應對象,例如Retrofit,ApplicationContext等。您將創建一個組件接口,在其中定義將模塊類的依賴項注入到哪里。

我正在使用:翻新,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中評論了構造函數注入。 我在那邊有場注入。 但是由於出現如上所述的錯誤,所以我無法構建項目。

任何幫助將不勝感激。 讓我知道是否需要其他與​​代碼相關的東西。

提前致謝。

編輯: PS:我知道答案,但我只是不明白為什么字段注入即@Inject APIEndPoints mApiEndPoints; 在HomePresenter中不起作用。 請有人給我解釋。

如您所見,我在HomePresenter中評論了構造函數注入。 我在那邊有場注入。

如果使用構造函數注入,然后匕首會為你創建對象,什么都知道。

如果你使用字段注入,那么必須創建對象,並告訴匕首了。

我不明白為什么在這種情況下您更喜歡使用字段注入,但是使用字段注入時,您需要向模塊之一添加帶@Provides注釋的方法,以使Dagger可以訪問演示者。

與錯誤狀態一樣,您需要在模塊中使用Construcotr注入或@Provides注釋的方法。

您正在混淆依賴關系生成器機制和依賴關系消耗機制。 帶注釋的字段用於消耗依賴項。 在您的情況下, @Inject HomePresenter homePresenter告訴Dagger“嘿,我希望您在此處注入HomePresenter”。 為此,Dagger需要您定義一個@Provides方法或使用@Inject注釋對象構造函數。

根據經驗,請始終使用@Inject批注的構造函數來提供依賴關系。 僅當您提供的對象是@Provides一種時,才應使用@Provides方法提供程序:

  • interface
  • abstract
  • 來自外部庫的對象(您無權訪問構造函數)
  • 提供之前需要自定義的對象

在您的情況下,由於沒有@Provides注釋方法或@Inject注釋構造函數,因此出現錯誤。 您應該取消對構造函數的注釋,因為這是您遇到的情況的處理方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM