2017-10-14 9 views
0

Presenter를 주입하는 MainActivity가 있고, 발표자 객체가 상호 작용자를 삽입하고 상호 작용 객체가 APIHelper를 주입합니다. 발표자, 상호 작용자 및 APIHelper의 모든 공급자는 MainModule에 있습니다. 내가 좋아하는 인터랙을 내 발표자 구현에서Dagger2가 종속성을 완전히 해결하지 못함

DaggerMainActivityComponent.builder() 
       .mainActivityModule(new MainActivityModule(MainActivity.this)) 
       .build().inject(this); 

:

@Module 
public class MainActivityModule { 
private final MainActivity activity; 
//Context context; 

public MainActivityModule (MainActivity activity) { 
    this.activity = activity; 
} 



@Provides 
@Singleton 
public MainViewPresenter providesMainPresenter(){ 
    return new MainPresenterImpl(activity); 
} 

@Provides 
@Singleton 
ListingInteractor providesInteractor(){ 
    return new ListingInteractorImpl(activity); 
} 

@Provides 
@Singleton 
ApiHelper providesAPI(){ 
    return new ApiHelper(activity); 
} 

} 

나는 같은 MainActivity에서 구성 요소를 주입 한

public class MainPresenterImpl implements MainViewPresenter { 
     Context context; 
    private MainView mainView; 
    // @Inject 
    ListingInteractor interactor; //here i get null interactor 
    MyScrollListener scrollListener; 

    public MainPresenterImpl(MainActivity activity) { 

     this.context = activity; 
     this.mainView = activity; 
    } 
    @Override 
    public void getCatFacts() { 
     interactor.getFacts(); 
    } 

내 인터랙 구현 클래스는 그 생성자에 필요한 API 도우미가 있습니다 컨텍스트

public class ListingInteractorImpl implements ListingInteractor{ 
    private Context context; 
    @Inject 
    private APIHelper; // getting null APIHelper 



    public ListingInteractorImpl(Context context) { 
     this.context = context; 

    } 

내 컴포넌트 인터페이스 같은 것입니다 :

@Component(modules={MainActivityModule.class}) 
@Singleton 
public interface MainActivityComponent { 



    void inject(MainActivity mainActivity); 

    /*void inject(MainPresenterImpl presenter);*/ 



    MainViewPresenter getMainPresenter(); 

    ListingInteractor getInteractor(); 

    ApiHelper getHelper(); 
} 

하지만 발표자 객체는 MainActivity에 인터랙, APIHelper는 모든 종속성을 해결해야 단검을 null.According되는 포함 발표자의 다른 모든 개체가 생성됩니다.

+0

대거 구성 요소에 발표자를 삽입합니까? 그렇지 않으면 나는 그것이 효과가 있다고 생각하지 않는다. 일반적으로 활동에는 @Inject Presenter p가 있습니다. 그리고 발표자는 반복자 또는 당신이 주입하고자하는 것이 무엇이든지 그의 생성자에 주입합니다. 그러므로 표현 자 생성자는 MainPresenterImpl (activity, iterator)가 될 것입니다. 그리고 대거는 모듈에 iterator를 제공했는지 알 수 있습니다 (명확한 경우 donno) – Eselfar

+0

대거를 사용하는 방법과 작동 방식에 대한 몇 가지 기본 사항이 누락 된 것처럼 보입니다. Dagger 2 Users Guide를 다시 읽거나 다른 자습서를 읽고 종속성을 제공하거나 주입하는 방법을 알고 있는지 확인하십시오. –

+0

@Eselfar 구성 요소 인터페이스 용 코드를 추가했습니다. 발표자가 컴포넌트에 있지만 MainActivity에서 초기화되고 있지만 발표자 내부에 삽입 한 객체가 상호 작용자 및 apihelper와 같이 초기화되지 않았습니다. – ozmank

답변

0

단검은 마법이 아니다. 그렇게하지 않는다면 원하는 곳마다 마술처럼 개체를 삽입하지 않습니다.

public class MainPresenterImpl implements MainViewPresenter { 
    // ... other fields ... 
    @Inject 
    ListingInteractor interactor; 

    public MainPresenterImpl(MainActivity activity) { 
    this.context = activity; 
    this.mainView = activity; 
    } 
} 

대거에게 이것은 아무 것도 없습니다. 필드 주입을 위해 일부 필드 (ListingInteractor)를 표시했으나 수동으로 구성 요소를 호출하여 객체를 주입하지 않으면 아무 일도 일어나지 않습니다. 필드 주입은 평균 클래스가 아닌 생성자에 인수를 추가 할 수없는 활동 및 단편에 대해 예약되어야합니다. 대신 단검 당신을 위해 MainPresenterImpl을 생성시키는의

@Provides 
@Singleton 
MainViewPresenter providesMainPresenter(){ 
    return new MainPresenterImpl(activity); 
} 

, 당신은 단지 활동에 통과, 자신 에 전화를 걸. MainPresenterImpl.interactor에 대한 호출이 없으므로 null이됩니다. 필드 주입을 사용하지 않고, 생성자를 직접 호출하고 필드를 할당하지 않습니다.
추가 설정이 필요한 객체의 경우 모듈에서 객체를 수동으로 생성해야합니다 (예 : Retrofit 또는 OkHttp, 빌더 포함).

필드를 설정하려면 필드 주입을 사용하여 구성 요소 (해당 inject(FieldInjectableClass clazz) 메쏘드)에 객체를 등록하고 코드 전체에 component.inject(myObject)을 뿌리면 정말 좋지 않을 것입니다. 필요없는 보일러판을 많이 작성했습니다.

더 합리적인 방법은 종속성을 속하는 생성자로 이동하는 것입니다.

public MainPresenterImpl(MainActivity activity, ListingInteractor interactor) { /* ... */ } 

다른 클래스에 대한 종속성이있는 경우 왜 그렇게 선언하지 않으시겠습니까? 그러나 이것은 대거가 그 일을하도록하는 대신에 당신 자신의 물건을 만드는 보일러 판을 여전히 남겨 둡니다.

그런 이유로 생성자 삽입을 사용해야합니다. 이름에서 알 수 있듯이, 그것은 생성자에 관한 것입니다. 클래스

@Inject // marked for constructor injection! 
public MainPresenterImpl(MainActivity activity, ListingInteractor interactor) { /* ... */ } 

지금 단검이 진입 점에 대해 알고 있으며를 만들 수 있습니다 : 그냥 @Inject 주석을 추가 할 수 있습니다.

는 단검을 사용하면 클래스 자체에 @Singleton 범위를 추가 (클래스가 아닌 생성자를 주석) 및 단지에 대한 @Provides 방법 (대한 개체에 대한 모듈의 방법을 제공 할 필요가 없습니다를 삭제할 수 일을 처리하도록하려면 그 돈 추가 설정 필요) 인터페이스에 구현을 바인딩하기 때문에 인터페이스에 바인딩 할 클래스를 지정해야합니다.

@Provides 
@Singleton 
MainViewPresenter providesMainPresenter(MainPresenterImpl implementation){ 
    return implementation; 
} 

대거 당신이 당신의 인터페이스 구현을 반환 할 수 있습니다 생성자 분사 MainPresenterImpl을 만들 수 있으며, 단검 그냥 따라 클래스 인스턴스를 적용하므로, 경우에 생성자 서명 변경 코드를 업데이트 할 필요가 없기 때문에.

이렇게 생성자 삽입을 사용하고 구현을 인터페이스에 바인딩하는 방법입니다. 그리고 언급했듯이, 나는 기초에 대해 높이 평가할 것을 권합니다. 단검이하는 일과 작동 방식을 이해했는지 확인하십시오. 필드 및 생성자 주입의 차이점이나 모듈을 사용하는시기를 알고 있어야합니다.

지금 단검을 배우는 데 드는 시간은 디버깅과 오류가 훨씬 줄어 듭니다. 모듈은 추상적 또는 인터페이스 인 경우


은 또한 단검이 바로 위의 상용구 코드를 생성합니다 @Binds 방법을 사용할 수있다.

@Binds 
@Singleton 
MainViewPresenter providesMainPresenter(MainPresenterImpl implementation); 
0

변경 다음 MainPresenterImpl & ListingInteractorImpl 생성자와 @Inject 그들 앞에 :

 

    @Inject 
    public MainPresenterImpl(MainActivity activity, ListingInteractor interactor) {...} 

    @Inject 
    public ListingInteractorImpl(Context context, APIHelper helper) {...} 
 

그런 다음 모듈의 구현 :

 

    @Provides 
    @Singleton 
    public MainViewPresenter providesMainPresenter(ListingInteractor interactor){ 
     return new MainPresenterImpl(activity, interactor); 
    } 

    @Provides 
    @Singleton 
    ListingInteractor providesInteractor(APIHelper helper){ 
     return new ListingInteractorImpl(activity, helper); 
    }