如何组织Dagger2模块和使用单活动应用程序时的组件

时间:2017-03-16 21:52:54

标签: android dependency-injection dagger-2 conductor

我有一个应用程序,让我们说15个屏幕。 有三个主要的,完全独立的活动:

  • LoginActivity - 非常明显的一些,一些登录的东西
  • MainActivity - 最重要的一个,最重要的是
  • TheOtherOneNotRelevantAtTheMoment

我决定使用Conductor,因为我发现Fragment的生命周期过于复杂,对我来说Conductor现在已经是#hot;"

我有很多导体控制器。其中大部分都与XXXListController相对应XXXDetailController。所有这些控制器在MainActivity内只能 。它类似于"单一活动 - 应用程序"。引入LoginActivity主要是因为来自第三方OAuth的回调,如FbLogin&谷歌登录。我只是想让MainActivity完全成为我的 - 没有任何其他奇怪的行为。

为了稍微组织依赖关系,我决定使用Dagger2。我在Spring和JavaEE方面有很好的经验,所以我觉得很容易。

我认识到几个模块没有任何问题:

AppModule - 与我的App相关的东西,如服务器地址等 AndroidModule - 包含SharedPreferencesApplication

等内容

然后我几乎"即兴创作"如何组织我的观点。这就是我所拥有的:

  • 另外3个范围:ActivityScopeControllerScopeServiceScope - 不相关。
  • 每个Controller都拥有相应的Module& Component。我已经读到这可能不是一个好主意,但我对此感到满意 - 每个Controller都非常独立,并拥有自己独特的依赖关系。
  • ApplicationComponent当然是层次结构的根源。
  • MainActivityComponent@Subcomponent
  • ApplicationComponent
  • XXXControllerComponent@Subcomponent
  • MainActivityComponent

要在我正在使用的MainActivity中注入依赖项,我发现这段代码很常见:

protected void injectDependencies(ApplicationComponent component) {
    component.plus(new MainActivityModule(this)).inject(this);
}

当我想创建&将依赖项注入我的Controller

MainActivity如下所示:

@ActivityScope
@Subcomponent(modules = {
        MainActivityModule.class
})
public interface MainActivityComponent {

    XXXListComponent newXXXListComponent(XXXListModule xxxListModule);

    void inject(MainActivity activity);
}

目前,典型的Controller看起来像这样:

@ControllerScope
@Subcomponent(modules = {
        XXXListModule.class
})
public interface XXXListComponent {
    void inject(XXXListController controller);
}

和相应的Module

@Module
public class XXXListModule {

    private XXXListController listController;

    public XXXListModule(XXXListController listController) {
        this.listController = listController;
    }

    @Provides
    @ControllerScope
    public XXXListController getMainView() {
        return ListController;
    }
// other not important
}

基本上每个Controller都应该是单身人士 - 我不想在MainActivity内部设置两个实例 - 但这不是“必须拥有的”。

问题是如何以正确的方式创建Controller。目前,MainActivity按如下方式执行:

router.pushController(RouterTransaction.with(new XXXListController()));

我不确定这一点,为什么要手动创建Controller

Controller中的onCreateView()内我注入了所有必需的依赖项 - 在我看来非常难看:

((MainActivity) getActivity()).getMainActivityComponent()
    .newXXXListComponent(new XXXListModule(this))
    .inject(this);

这个长长的问题可以帮助我组织我对Dagger的了解 - 也许有人觉得它很有帮助。但!对于那些达到这条线的Stackoverflowers来说,这是一个好方法还是还有其他更好的方法吗?

1 个答案:

答案 0 :(得分:0)

我不确定我是否完全理解您的问题,但由于您有多个活动,您可能希望在应用程序而不是MainActivity中进行注入。 否则他们将不再是单身人士,因为当你在他们之间移动时,活动会被重新创建。例如,如果您创建一个名为ConductorApplication的类:

public class ConductorApplication extends Application {
    static AppComponent app_component;
    static ClockComponent component;

    @Override
    public void onCreate() {
        super.onCreate();
        app_component = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
        component = createComponent();
    }



    protected ClockComponent createComponent() {
        return DaggerClockComponent.builder().build();
    }

    public static ClockComponent getClockComponent() {
        return component;
    }

    public ClockComponent component() {
        return component;
    }

    public static AppComponent GetAppComponent() {
        return app_component;
    }
}

然后在你的控制器内部创建,例如在inflateView()

内的HomeController
public class HomeController extends BaseController {

    private HomeViewModel homeViewModel;
    private ControllerHomeBinding binding;


    @Inject
    Clock clock;

    @NonNull
    @Override
    protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
        ConductorApplication.getClockComponent().inject(this);
        return inflater.inflate(R.layout.controller_home, container, false);
...
}

如果您还没有,可能需要添加:

<application 
    android:name=".ConductorApplication" 
    ...
    <activity
        android:name=".MainActivity"
        ...
    </activity>
</application>

AndroidMainifest.xml