2015-03-13 11 views
6

mam setup moduleA jako dostawcy aplikacji szeroki Singleton ModuleB jako dostawca obiektów związanych użytkownikaDagger v2: wstrzykiwać 2 różne zakresy w jeden obiekt

Moja użytkownik wyświetlacz fragment będzie wykorzystać szeroki magistrali systemowej, aby wysłać wiadomość do innych, użyj obiektu związanego z użytkownikiem do wyświetlenia.

Problem nie może wstrzyknąć innej klasy scrope w jeden obiekt. Metoda component.getX działa dobrze, ale preferowane jest wstrzykiwanie. Komunikat Błąd: @UserScope nie może odwoływać się powiązania z zakresów różnica: @Provides @Singleton Bus ModuleA.provideBus()

@Module 
public class ModuleA { 
    @Provides @Singleton Bus provideBus() {...} 
} 

Moduł B jako dostawca informacji związanych użytkownika

@Module 
public class ModuleB{ 
    private final User user; 
    public ModuleB(User user) {...} 
    @Provides @UserScope User provideUser() {} 
    @Provides @UserScope UserManager provideUserManager() {} 
} 

konfiguracji Components na przykład:

@Component (modules={ModuleA.class}) 
@Singleton 
public interface ComponentA { 
    Bus getBus(); 
    void inject(ClassA target); 
} 

@Component(modules={ModuleB.class}) 
@UserScope 
public interface ComponentB { 
    User getUser(); 
    UserManager getUserManager(); 
    void inject(ClassA target); 
} 


class UserFragment exrtends Fragment { 
    @Inject Bus bus; 
    @Inject UserManager userManager; 
    public void onCreate() { 
     getComponentA().inject(this); 
     getComponentB().inject(this); 
    } 
} 

Odpowiedz

20

Wypróbuj tę konfigurację, działa dla mnie . Naprawdę brakuje dobrej dokumentacji o Dagger2, więc przestudiowałem kilka przykładów kodu open-source, które można znaleźć w GitHub itp. Według słów kluczowych, takich jak Dagger2.

Poziom podawania Składnik

@Singleton 
@Component(modules = AppModule.class) 
public interface AppComponent { 
    // exported for child-components 
    Bus eventBus(); 
} 

Moduł poziom Zastosowanie

@Module 
public class AppModule { 
    @Provides @Singleton 
    Bus provideBus() { 
     return BusProvider.getInstance(); 
    } 
} 

poziom aktywny składnik

@ActivityScope 
@Component(dependencies=AppComponent.class, modules=MainActivityModule.class) 
public interface MainActivityComponent { 
    void inject(MainActivity mainActivity); 
} 

Moduł Poziom aktywności

@Module 
public class MainActivityModule { 
    private final MainActivity mActivity; 

    public MainActivityModule(MainActivity activity) { 
     mActivity = activity; 
    } 

    @Provides 
    MainActivityTitleController provideTitleController() { 
     return new MainActivityTitleController(mActivity); 
    } 
} 

Android klasy Application

public class MyApplication extends Application { 
    private AppComponent mAppComponent; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     // Dagger2 
     mAppComponent = Dagger_AppComponent.builder() 
      .appModule(new AppModule(this)) 
      .build(); 
    } 

    public AppComponent getComponent() { 
     return mAppComponent; 
    } 

    public static AppComponent getComponent(Context context) { 
     return ((MyApplication)context.getApplicationContext()).getComponent(); 
    } 
} 

I wreszcie aktywny

public class MainActivity extends ActionBarActivity { 

    // Injectable fields 
    @Inject Bus mEventBus; 
    @Inject MainActivityTitleController mTitleController; 

    private MainActivityComponent mComponent; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // Dagger2 
     mComponent = Dagger_MainActivityComponent.builder() 
      .appComponent(((MyApplication)getApplication()).getComponent()) 
      .mainActivityModule(new MainActivityModule(this)) 
      .build(); 
     mComponent.inject(this); 
    } 
} 
+4

Co się stanie, jeśli "MainActivityComponent" jest podkomponentem? –

7

Myślę, że głównym problemem w swoich fragmentów kodu masz zapewnione, że ModuleB powinien mieć zależność ModuleA prawidłowo dostarczyć singleton z powodu błędu, który otrzymujesz. To znaczy. to powinno działać:

@Component(modules={ModuleB.class}, dependencies = ComponentA.class) 
@UserScope 
public interface ComponentB { 
    User getUser(); 
    UserManager getUserManager(); 
    void inject(MainActivity target); 
} 

I odtworzył swoje klasy i kilka założeń, aby wypełnić puste pola i wydaje się działać prawidłowo. Możesz zobaczyć pełny działający kod: here on GitHub. Jedyną różnicą w moim kodzie jest to, co nazywasz ClassA/UserFragment Właśnie nazwałem MainActivity, ale poza tym struktura jest taka sama.

Powiązane problemy