Dagger v2:将2个不同的范围注入一个对象

Xia*_*eng 10 android dagger-2

我将moduleA设置为应用程序范围的单例提供程序,ModuleB作为用户相关的对象提供程序

我的用户显示片段将使用系统总线向他人发送消息并使用用户相关对象进行显示.

问题不能将不同的scrope类注入一个对象.使用component.getX方法工作正常,但注入是首选方式.错误消息: @ UserScope可能无法引用具有差异范围的绑定:@Provides @Singleton Bus ModuleA.provideBus()

@Module
public class ModuleA {
  @Provides @Singleton Bus provideBus() {...}
}
Run Code Online (Sandbox Code Playgroud)

模块B作为用户相关的信息提供者

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

组件设置如下:

@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);
   }
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*uts 23

尝试这个配置,它适合我.实际上缺乏关于Dagger2的良好文档,因此我研究了一些开源的代码示例,您可以在GitHub等中找到像Dagger2这样的关键字.

应用程序级组件

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

应用级模块

@Module
public class AppModule {
    @Provides @Singleton
    Bus provideBus() {
        return BusProvider.getInstance();
    }
}
Run Code Online (Sandbox Code Playgroud)

活动级别组件

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

活动级别模块

@Module
public class MainActivityModule {
    private final MainActivity mActivity;

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

    @Provides
    MainActivityTitleController provideTitleController() {
        return new MainActivityTitleController( mActivity );
    }
}
Run Code Online (Sandbox Code Playgroud)

Android应用程序类

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

最后活动

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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果`MainActivityComponent`是一个子组件怎么办? (8认同)

G. *_*ard 9

我认为你提供的代码片段中的主要问题是你ModuleB应该依赖于ModuleA正确地为单例提供你得到的错误.即这应该工作:

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

我重新创建了你的类并做了一些假设来填补空白,它似乎工作得很好.您可以在GitHub上看到完整的工作代码.我的代码唯一的区别是,你所谓的ClassA/ UserFragment我刚刚调用,MainActivity但结构是相同的.