使用Dagger 2在库模块中注入应用程序上下文 [英] Injecting application context in library module with Dagger 2

查看:114
本文介绍了使用Dagger 2在库模块中注入应用程序上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建具有以下功能的应用程序:ContentProvider,SyncAdapter,Job服务和相关的持久性逻辑.这些最上面是带有UI的活动".我试图将所有所说的功能放在一个单独的库模块中,因为从理论上讲,它们的逻辑是独立的,并且可以在任何应用程序中重复使用.

I'm building an app with some features: a ContentProvider a SyncAdapter, a Job service and related persistence logic. On top on these there are the Activities with the UI. I'm trying to put all said features in a separate library module, because in theory their logic is stand-alone and would be reusable by any application.

现在是Dagger2.库的依赖关系图的第一个节点(主要组件)确实需要提供Context,并且必须从Application注入此Context,因为库作用域具有与应用程序相同的生命周期.为了自给自足,很显然,我的库不应该直接使用我的Application类.

Now comes Dagger2. The first node (main Component) of my library's dependency graph does need to provide Context, and this Context has to be injected from the Application, because the library scope has the same lifecycle of the application. To be self contained, obviously, my library should not directly use my Application class.

这些是我想到的可能性:

These are the possibilities I thought of:

  • 在我的应用程序中构建库的主要组件,然后按照建议的此处所述).尽管它增加了额外的复杂性,但这似乎是可行的.
  • 最后但并非最不重要的一点是,放弃对组件进行模块化的尝试,因为依赖于应用程序上下文破坏了模块化的概念.
  • Build the library's main Component in my Application and store it in a global static class/enum as suggested here but I'm concerned that using such a static reference could be an anti-pattern.
  • Pack in the library an Application class which builds the library scoped Component, cast app context to this class in the library to use the component and then extend this Application class on the main app. This works, but if there's more than one library it's not viable anymore.
  • Use the factory pattern: put provision methods in the library component that provide the factory which in turn is given the locally available context as a parameter. (As explained here). This seems viable, although it adds extra complexity.
  • Last but non the least, give up trying to modularize the components, since being dependent on the application context breaks the concept of modularity.

正确的方法是什么?

推荐答案

Dagger 2 for Android 进行营救.它提供了AndroidInjector的概念,它是一个Component,可用于以静态方式注入实例,而无需了解依赖项提供程序.此外,使用开箱即用提供的Dagger-前缀类,注入的依赖项看起来像是无处可来.很棒.

Dagger 2 for Android comes to the rescue. It provides the concept of AndroidInjector, which is a Component that can be used to inject an instance in a static way, without having to know the dependency provider. Moreover, using the Dagger- prefixed classes provided out of the box, the injected dependencies look like coming from nowhere. Awesome.

所有您需要做的就是在库中声明一个顶级Module,该顶级Module安装在应用程序Component中.此Module将提供库所需的所有依赖项和SubComponent,它们将自动继承您在依赖关系图中播种的@AppContext Context,准备将其注入库中的任何位置以及每个依赖项您通过主应用程序Component提供.

All you have to do is declare in the library a top-level Module which is installed in the Application Component. This Module will provide all the dependencies and the SubComponents needed by the library, which will automatically inherit the @AppContext Context that you seeded in the dependency graph, ready to be injected anywhere in you library, as well as every dependency you provide through the main Application Component.

这是一个简短的示例(用Kotlin编写):

Here's a short example (written in Kotlin):

@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)
        }
    }
}

扩展示例

Application子类的示例:

An example of the Application subclass:

// 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);
}

在您的Android库中:

And in your Android library:

@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)
    }
}

这篇关于使用Dagger 2在库模块中注入应用程序上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆