2017-12-21 62 views
1

몇 가지 기능으로 응용 프로그램을 만들고 있습니다 : ContentProvider SyncAdapter, 작업 서비스 및 관련 지속성 논리. 이들 위에 UI가있는 활동이 있습니다. 나는 모든 기능을 별도의 라이브러리 모듈에 넣으려고하고있다. 왜냐하면 이론적으로 로직은 독립형이며 어떤 애플리케이션에서도 재사용 할 수 있기 때문이다.대거 2 라이브러리 모듈의 응용 프로그램 컨텍스트 주입

이제 Dagger2가 온다. 내 라이브러리의 종속성 그래프의 첫 번째 노드 (주 구성 요소)는 컨텍스트를 제공해야하며 라이브러리 범위의 응용 프로그램 수명주기가 동일하므로이 컨텍스트를 응용 프로그램에서 주입해야합니다. 자체적으로 포함 되려면 분명히 내 라이브러리가 내 응용 프로그램 클래스를 직접 사용해서는 안됩니다.

이 내가 생각 가능성은 다음과 같습니다 here을 제안 내 응용 프로그램에서 라이브러리의 주요 구성 요소를 구축하고 글로벌 정적 클래스/열거에 저장

  • 하지만 나는 그런 정적 참조를 사용하는 것이 걱정 반 패턴 일 수 있습니다.
  • 라이브러리에 패키지를 포함하는 응용 프로그램 클래스는 라이브러리 범위의 구성 요소를 작성하고 라이브러리의이 클래스에 응용 프로그램 컨텍스트를 캐스팅하여 구성 요소를 사용하고 기본 응용 프로그램에서이 Application 클래스를 확장합니다. 이 방법은 작동하지만 둘 이상의 라이브러리가있는 경우 더 이상 사용할 수 없습니다.
  • 팩토리 패턴을 사용합니다. 로컬로 사용할 수있는 컨텍스트가 매개 변수로 제공되는 팩토리를 제공하는 프로비져닝 메소드를 라이브러리 구성 요소에 넣습니다. (설명한대로 here). 이것은 추가 복잡성을 추가하지만 실행 가능해 보입니다.
  • 애플리케이션 컨텍스트에 의존하기 때문에 모듈성의 개념이 깨지기 때문에 마지막으로 구성 요소를 모듈화하려고 포기해야합니다.

올바른 방법은 무엇입니까?

+0

같은 것을하고 싶습니다. 해결책을 찾았습니까? –

+0

나는이 질문에 대해 잊어 버렸다 :) 해결책을 찾았습니다. 내 대답은 아래를보십시오. – devrocca

답변

1

Dagger 2 for Android이 구해줍니다. 종속성 공급자를 알지 않고도 정적 방법으로 인스턴스를 주입하는 데 사용할 수있는 ComponentAndroidInjector의 개념을 제공합니다. 더욱이, 상자에서 제공되는 Dagger- 접두어로 묶인 클래스를 사용하면 주입 된 종속성이 아무데도 나타나지 않는 것처럼 보입니다. 굉장해.

응용 프로그램 Component에 설치된 최상위 레벨 Module을 라이브러리에 선언하기 만하면됩니다. 이 Module은 라이브러리에 필요한 모든 종속성과 SubComponent을 제공합니다. 종속성 그래프에 시드 (seed)로 넣은 @AppContext Context을 자동으로 상속하며 라이브러리의 어느 곳 으로든 삽입 할 준비가되고 기본 응용 프로그램을 통해 제공하는 모든 종속성을 자동으로 상속합니다 Component.

@Component(modules = [ 
    AndroidSupportInjectionModule::class, 
    AppModule::class, 
    LibraryModule::class //plug-in the library to the dependency graph 
]) 
@Singleton 
interface AppComponent : AndroidInjector<App> { 

    @Component.Builder 
    abstract class Builder : AndroidInjector.Builder<App>() { 

     @BindsInstance 
     abstract fun appContext(@AppContext context: Context) 

     override fun seedInstance(instance: App) { 
      appContext(instance) 
     } 
    } 
} 

편집 :

여기 (코 틀린로 작성) 짧은 예제 확장 예

응용 프로그램 서브 클래스의 예 :

// DaggerApplication provides out-of-the-box support to all the AndroidInjectors. 
// See the class' code to understand the magic. 
public class App extends DaggerApplication { 

@Override 
protected AndroidInjector<? extends DaggerApplication> applicationInjector() { 
    // We only provide its own Injector, the Application Injector, 
    // that is the previous AppComponent 
    return DaggerAppComponent.builder().create(this); 
} 

그리고 당신의 안드로이드 라이브러리 :

@Module 
public abstract class LibraryModule { 

    @ContributesAndroidInjector 
    public abstract LibraryActivity contributeLibraryActivityInjector(); 

} 

public class LibraryActivity extends DaggerAppCompatActivity { 

    @Inject 
    @AppContext 
    Context appContext; 

    @Override 
    protected void onCreate(@Nullable Bundle savedInstanceState) { 
     super.onCreate(savedInstanceSate); 
     // here you automagically have your injected application context! 
     ExternalSingleton.getInstance(appContext) 
    } 
} 
+0

일반적으로 의존성 삽입 프레임 워크는 라이브러리 내에서 사용하면 안됩니다. 응용 프로그램 수준 도구입니다. 라이브러리 내부의 Dagger를 사용하여 라이브러리에서 클래스를 노출하려는 이유는 무엇입니까? 클래스를 공개 (또는 하나의 정면을 추출)하고 lib의 대신에 응용 프로그램의 객체 그래프에 추가하면됩니다. – Vasiliy

+0

@Vasiliy Android 컨텍스트 (예 : 파일 저장, 캐싱 등)가 필요한 라이브러리 모듈이 있다면 어떻게 될까요? 왜 그런 경우 DI를 사용하는 것이 좋지 않은가요? –

+0

@devrocca 모듈에 Application 클래스가 없으면 어떻게 구현 했습니까? HasActivityInjector ** –