【问题标题】:How to organize Dagger2 modules & components when using single-activity-application使用单活动应用程序时如何组织 Dagger 2 模块和组件
【发布时间】:2017-03-16 21:52:54
【问题描述】:

我有一个应用程序,假设有 15 个屏幕。 有 3 个主要的、完全独立的活动:

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

我决定使用Conductor,因为我发现Fragment 的生命周期太复杂了,而Conductor 对我来说现在是“热狗”

我有很多指挥家的控制器。他们中的大多数都像XXXListController 和相应的XXXDetailController。所有这些控制器存在于MainActivity 内。这有点像“单一活动应用程序”。 LoginActivity 的引入主要是由于来自第三方 OAuth 的回调,例如 FbLogin 和 Google Login。我只是想让MainActivity 完全属于我——没有任何其他奇怪的行为。

为了稍微整理一下依赖关系,我决定使用 Dagger2。我在 Spring 和 JavaEE 方面有很好的经验,所以我认为这很容易。

我认出了几个没有任何问题的模块:

AppModule - 与我的应用程序相关的东西,如服务器地址等 AndroidModule - 像 SharedPreferences, Application

然后我几乎“即兴发挥”了如何组织我的观点。这就是我所拥有的:

  • 另外 3 个作用域:ActivityScopeControllerScopeServiceScope - 不相关。
  • 每个Controller 都有自己对应的ModuleComponent。我读到这可能不是一个好主意,但我可以接受 - 每个Controller 都非常独立,并且有自己独特的一组依赖项。
  • ApplicationComponent 当然是层次结构的根。
  • MainActivityComponent@SubcomponentApplicationComponent
  • XXXControllerComponent@SubcomponentMainActivityComponent

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

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

当我想为我的Controllers 创建和注入依赖项时出现问题。

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

onCreateView() 中的Controller 中,我已经注入了所有需要的依赖项——在我看来,这是一种非常丑陋的方式:

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

这个长问题帮助我整理了关于 Dagger 的知识——也许有人觉得它有帮助。但!对于那些到达这条线的Stackoverflowers,这是一个好方法还是有其他更好的方法来做到这一点?

【问题讨论】:

  • 有人想发声吗?

标签: android dependency-injection dagger-2 conductor


【解决方案1】:

我不确定我是否完全理解您的问题,但由于您有多个活动,您可能希望在应用程序而不是 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

【讨论】:

    猜你喜欢
    • 2015-10-28
    • 1970-01-01
    • 2017-11-20
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多