2017-04-21 2 views
1

저는 Dagger 2를 처음 접했고 "구성 가능한 구성 요소"를 가질 방법을 찾고 있습니다.대거 2 모듈 "인터페이스"?

public interface ErrorReporter{ 
    ... 
} 

public class ConsoleErrorReporter implements ErrorReporter{ 
    ... // Print to System.err 
} 

public class DialogErrorReporter implements ErrorReporter{ 
    ... // Show modal dialog to user 
} 


@Module 
public interface UIModule{ 
    @Provides 
    ErrorReporter provideErrorReporter(); 
} 

@Module 
public class ConsoleUIModule{ 
    @Override 
    @Provides 
    ErrorReporter provideErrorReporter(ConsoleErrorReporter cer){ 
     return cer; 
    } 
} 


@Module 
public class GraphicalUIModule{ 
    @Override 
    @Provides 
    ErrorReporter provideErrorReporter(DialogErrorReporter der){ 
     return der; 
    } 
} 

@Component(modules = {UIModule.class, OtherUniversalModule.class}) 
public interface ApplicationComponent{ 
    ErrorReporter errorReporter(); 
} 


void main(String[] args){ 
    final UIModule uiModule; 
    if(args.length == 1 && args[0].equals("gui")){ 
     uiModule = new GraphicalUIModule(); 
    }else{ 
     uiModule = new ConsoleUIModule(); 
    } 

    DaggerApplicationComponentdac = DaggerApplicationComponent.builder() 
             .uiModule(uiModule).build(); 
    dac.errorReporter().showError("Hello world!"); 
} 

는 위의 인터페이스와 추상 클래스에 대한 @Provides methods cannot be abstract 불행하게도 모두 실패

는 기본적으로이 내가 달성하고자하는 것입니다. 나는 또한 null을 리턴 한 후 서브 클래스에서 이것을 오버라이드하는 구체적인 구현을 가진 비 추상적 인 기본 클래스를 시도했다. 그러나 이것은 또한 @Provides methods may not override another method으로 실패합니다.

요약하면 모듈에 대한 계약을 정의하고 런타임 중에 다른 모듈을 선택하고자합니다. Dagger 2 컴파일 시간이 객체 그래프의 유효성을 검사한다는 것을 알고 있지만, 여전히 올바르게 정의되어 있어야하는 잘 정의 된 계약이 있다면? 아니면 두 사용자 인터페이스에 대해 중복 코드가있는 두 개의 다른 구성 요소를 만들어야합니까? 내가 누락 된 다른 해결책이 있습니까?

답변

2

I하지

이것은 ConsoleUIModule가 필요하다 것을 의미 당신이 당신의 클래스

@Inject ConsoleErrorReporter(Console console); 

@Inject DialogErrorReporter(Graphics graphics); 

을 위해 다음과 같은 두 가지 생성자가 있다고 가정 ... 때문에,이 방법이 가능 모듈을 사용하여 생각 ConsoleDialogErrorReporterErrorReporter의 다시 구현 구현을 만들려면 Graphics 개체가 필요합니다.

그러나 단검이 약 UIModule 인 경우 인터페이스를 사용하기 때문에 ... 음 ... 어떤 것에 대해서도 알지 못하기 때문에 어느쪽에 대해서도 종속성을 제공 할 수 없습니다.

종속성 빌드를 모르는 경우 컴파일시 종속성 그래프가 작동하지 않습니다. provideErrorReporter(ConsoleErrorReporter cer)provideErrorReporter()을 덮어 쓰지 않기 때문에 단검 없이도 컴파일되지 않습니다.


다른 구성 요소를 사용하면됩니다. 구성 요소는 실제로 사물을 제공하는 방법을 알고 있기 때문입니다. 그리고 구성 요소는 이미 인터페이스 —이고 원하는 것은 맞습니까?

하나의 구성 요소가 다른 구성 요소에 종속되므로 구성 요소 종속성을 가질 수 있습니다. 예 : ErrorReporter의 구현이 필요한 NeedsErrorReporter을 제공하는 DependentComponent이 있어야합니다.

그런 다음 실제 구성 요소로 인터페이스를 구현하고 각 구성 요소에는 해당 모듈이 있습니다 (그리고 더 많은 종속성이있을 수 있습니다.) 또한 실제 구성 요소가 아닌 인터페이스에 의존합니다.). 결국 당신은 바꿀 수있는 구성 요소를 가지며 적절히 캡슐화 된 다른 버전의 객체를 제공하게됩니다!

@Component(dependencies = UIComponent.class) /* <- an interface! */ 
interface DependentComponent { 
    NeedsErrorReporter needsErrorReporter(); 
} 

class NeedsErrorReporter { 
    @Inject public NeedsErrorReporter(ErrorReporter reporter) { } 
} 


/* this is _not_ a component, but a simple interface! */ 
interface UIComponent { 
    ErrorReporter errorReporter(); 
} 


/* Console */ 
@Component(modules = ConsoleUIModule.class) 
interface ConsoleUIComponent extends UIComponent { } 

@Module interface ConsoleUIModule { 
    @Binds ErrorReporter provideErrorReporter(ConsoleErrorReporter cer); 
} 

/* Graphic */ 
@Component(modules = GraphicalUIModule.class) 
interface GraphicUIComponent extends UIComponent { } 

@Module interface GraphicalUIModule { 
    @Binds ErrorReporter provideErrorReporter(DialogErrorReporter der); 
} 

/* The error reporter variants */ 
interface ErrorReporter { 
} 

class ConsoleErrorReporter implements ErrorReporter { 
    @Inject public ConsoleErrorReporter() { } 
} 

class DialogErrorReporter implements ErrorReporter { 
    @Inject public DialogErrorReporter() { } 
} 

이제 당신이 바로 그 구성 요소를 선택하기 만하면됩니다)

DaggerDependentComponent.builder().uIComponent(DaggerConsoleUIComponent.create()).build(); 
    // or 
DaggerDependentComponent.builder().uIComponent(DaggerGraphicUIComponent.create()).build(); 
+0

I 종류의 그것이 내가'를 통해 javac''로 컴파일 할 때, 작업이 컴파일 gradle'있어 ...하지만 어떤 이유로 "m2apt"(또는 w/e라고도 함)로 Eclipse에서 컴파일 할 때 "인터페이스 구성 요소"를 상속받은 구성 요소 중 하나에 대해 단검 구성 요소를 생성하지 않으면 오류가 발생합니다.이 문제가 발생했습니다 ? –

+0

@EmilyL.나는 annotation processor로 Eclipse를 사용한 적이 없기 때문에 솔직히 알지 못한다. 아마도 당신은 일식과 다른 단검 버전을 사용하고 있습니까? 나는'2.10'을 사용했다. –

+0

나는 eclipse 파일을 생성하기 위해 gradle에서'apt' 플러그인을 사용하고 있습니다. 그리고 그것은 같은 대거'2.10'임을 확인했습니다. 나는 더 깊게 파야 할 것 : / –

관련 문제