使用 Dagger 2 在库模块中注入应用程序上下文

2023-11-26

我正在构建一个具有一些功能的应用程序:ContentProvider、SyncAdapter、作业服务和相关的持久性逻辑。在这些之上是带有 UI 的活动。我试图将所有上述功能放在一个单独的库模块中,因为理论上它们的逻辑是独立的并且可以由任何应用程序重用。

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

这些是我想到的可能性:

  • 在我的应用程序中构建库的主要组件,并将其存储在全局静态类/枚举中,按照建议here但我担心使用这样的静态引用可能是一种反模式。
  • 在库中打包一个应用程序类,该类构建库范围内的组件,将应用程序上下文转换为库中的此类以使用该组件,然后在主应用程序上扩展此应用程序类。这是可行的,但如果有多个库,它就不再可行了。
  • 使用工厂模式:将提供方法放入提供工厂的库组件中,而工厂又被赋予本地可用的上下文作为参数。 (正如所解释的here)。这似乎是可行的,尽管它增加了额外的复杂性。
  • 最后但并非最不重要的一点是,放弃尝试模块化组件,因为依赖于应用程序上下文破坏了模块化的概念。

这样做的正确方法是什么?


匕首 2 安卓版来救援。它提供了以下概念:AndroidInjector,这是一个Component可以用于以静态方式注入实例,而无需知道依赖项提供程序。此外,使用Dagger-开箱即用提供前缀类,注入的依赖项看起来像是来自无处。惊人的。

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

这是一个简短的示例(用 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)
        }
    }
}

编辑:扩展示例

应用程序子类的示例:

// 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 库中:

@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)
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Dagger 2 在库模块中注入应用程序上下文 的相关文章

  • 使用workmanager时Firestore脱机持久性错误

    我正在使用一个WorkManger定期从我的中检索信息Firestore当应用程序处于后台和前台时的数据库 此信息用于根据状态更新 UI 因此不同的状态会添加或删除 UI 的不同部分 第一次运行时效果很好 但是 一旦应用程序处于后台并且Wo
  • 类型容器“Android 依赖项”引用不存在的库 android-support-v7-appcompat/bin/android-support-v7-appcompat.jar

    我在尝试在我的项目中使用 Action Bar Compat 支持库时遇到了某种错误 我不知道出了什么问题 因为我已按照此链接中的说明进行操作 gt http developer android com tools support libr
  • React Native 从 JavaScript 代码内部访问 strings.xml

    有没有办法访问当前值android app src main res values strings xml从 JavaScript 代码内部 我想为每个构建放置不同的端点 URL 但我什至无法检测到反应本机代码内的构建类型 而不必求助于 D
  • Sqlite数据库生命周期?关闭应用程序后它会被删除吗?

    我正在遵循一个简单的教程 该教程创建一个从 SQLiteOpenHelper 扩展的类 并创建一个包含一个表和 5 行的数据库 好的 但我需要更多地了解 android Sqlite 数据库 例如 如果应用程序关闭或手机关机会发生什么 数据
  • android中向sqlite中插入大量数据

    目前 我必须一次向我的 Android 中插入超过 100 亿条数据 然而 内存不足的问题会使程序崩溃 sqlite 插入测试非常简单 只需使用 for 循环生成 sql 插入命令并通过 开始 和 提交 进行包装 private Array
  • 找不到 com.google.firebase:firebase-core:9.0.0 [重复]

    这个问题在这里已经有答案了 在遵循有些不一致的指示之后here https firebase google com docs admob android quick start name your project and here http
  • Android 后退按钮无法与 Flutter 选项卡内的导航器配合使用

    我需要在每个选项卡内有一个导航器 因此当我推送新的小部件时 选项卡栏会保留在屏幕上 代码运行得很好 但是 android 后退按钮正在关闭应用程序而不是运行 Navigator pop import package flutter mate
  • CardView 圆角获得意想不到的白色

    When using rounded corner in CardView shows a white border in rounded area which is mostly visible in dark environment F
  • 无法获取log.d或输出Robolectrict + gradle

    有没有人能够将 System out 或 Log d 跟踪从 robolectric 测试输出到 gradle 控制台 我在用Robolectric Gradle 测试插件 https github com robolectric robo
  • 谷歌坐标认证

    当我尝试连接到 Google 坐标时 总是出现异常GoogleAuthException 我拥有 Google 地图协调中心许可证 我确实使用我的包应用程序名称和 SHA1 在 google 控制台中创建了我的客户端 ID 我将权限添加到清
  • 是否必须删除 Intent extra?

    这可能是一个愚蠢的问题 但是是否有一条规则规定消费活动必须显式删除 Intent 额外内容 或者只有在回收 Intent 对象时才如此 换句话说 如果我总是通过执行以下操作来链接到下一个活动 Intent i new Intent MyCu
  • 是否有 ADB 命令来检查媒体是否正在播放

    我想使用 ADB 命令检查根植于终端的外部设备中是否正在播放音频 视频 我无法找到任何 ADB 命令 如果有 我尝试过 adb shell dumpsys media player 我想要一个命令来指定视频是否正在运行 您可以使用以下命令查
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • Ubuntu 16.04 - Genymotion:找不到 /dev/hw_random

    I install Genymotion on the Ubuntu 16 04 64Bit I created a virtual emulator for Android 6 0 then I run this emulator but
  • 如何使用InputConnectionWrapper?

    我有一个EditText 现在我想获取用户对此所做的所有更改EditText并在手动将它们插入之前使用它们EditText 我不希望用户直接更改中的文本EditText 这只能由我的代码完成 例如通过使用replace or setText
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 在 android DatePickerDialog 中将语言设置为法语

    有什么办法可以让日期显示在DatePickerDialog用法语 我已经搜索过这个但没有找到结果 这是我的代码 Calendar c Calendar getInstance picker new DatePickerDialog Paym
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • 如何在Windows 10通用应用程序中使用WCF服务?

    我的 Windows 8 1 应用程序使用 WCF 服务 我需要将我的应用程序移植到 Windows 10 UWP 应用程序 但无法添加服务引用 当我添加服务引用时出现此消息 数据服务客户端代码生成失败 不支持指定的 Windows 应用商
  • 如何从字符串数组或数组列表创建字符串?

    我如何提取字符串 或数组列表中的所有元素 并将所有单词以正确的格式 带有单个空格 组合在一起 然后存储在数组中 String a Java is cool 输出 Java 很酷 Use a StringBuilder String stri
  • 如何加快 Eclipse 项目“刷新”速度

    我有一个相当大的 PHP 代码库 10k 文件 我在 Windows 计算机上使用 Eclipse 3 4 PDT 2 来处理它 而这些文件托管在 Debian 文件服务器上 我通过 Windows 上的映射驱动器进行连接 尽管有 1gbi
  • Ruby 相当于 PHP 的 $this

    相当于PHP的什么 this gt 在鲁比 红宝石相当于this is self 它们都指当前实例 棘手的部分是在 Ruby 类范围内 self指的是该类的当前实例Class它定义了您正在构建的类 在方法内部 self指类的实例 eg cl
  • 在 x86-64 中将寄存器移至自身有什么好处

    我正在 x86 64 NASM 中做一个项目 并遇到了指令 mov rdi rdi 在我的教授写的编译器的输出中 我已经进行了全面搜索 但找不到提及为什么需要这样做 它会影响标志还是我不明白的聪明之处 为了提供一些上下文 它在同一寄存器递减
  • Google Analytics API 错误“无法同时查询选定的维度和指标。”

    我必须同时从 GA 电子商务中检索尽可能多的不同指标 我正在使用 google api ruby 客户端 并且不断出现错误 message gt Selected dimensions and metrics cannot be queri
  • 存档上传失败并出现错误:ITMS-90470 缺少 TVTopShelfImage.TVTopShelfPrimaryImageWide 密钥

    您知道为什么会发生这种情况以及最重要的是如何解决它吗 添加具有什么值的密钥 从 tvOS 10 开始 您必须包含宽顶架图像 Top Shelf Image Wide 大小为2320px by 720px 1x tvOS 人机界面指南 图标和
  • 无法加载 share\octave\packages 中可用但未在 share\octave\octave_packages 中列出的包

    短篇故事 在目录中 octave 4 2 1 share octave packages最初有 45 个包子目录 其中 m和其他文件 例如financial 0 5 0 但我找不到使用它们的方法 更详细 我已经解压了便携式 zip 版本Oc
  • 使用 rxjs 实现指数退避

    角7docs提供这个实际用法的例子rxjs Observable为 AJAX 请求实现指数退避 import pipe range timer zip from rxjs import ajax from rxjs ajax import
  • 将rtf或文本文件加载到UITextView iphone sdk中

    嗨 我想知道如何将 rtf 或文本文件加载到 UITextView 中 我使用了几个代码 但不起作用 NSString filePath NSBundle mainBundle pathForResource filename ofType
  • 使用 itext 5.5.5 进行数字签名

    我从 iText 升级5 2 1到iText5 5 5 我使用 PdfStamper 和 PdfSignatureApperance 来应用数字签名 这是我的代码片段 PdfStamper stamper PdfStamper create
  • 第二个 AsyncTask 未执行

    我有 2 个 AsyncTask 一个正在创建套接字连接 另一个正在使用这些套接字传输对象 我的代码是这样的 try connectat true transmitter new SocketTransmitter transmitter
  • 无锁和无锁有什么区别?

    在一些关于算法的文章中 有些使用这个词lockfree 还有一些使用lockless 有什么区别lockless and lockfree 谢谢 Update http www intel com content dam www publi
  • 计算 UITextView 中的行数,按帧大小包裹的行数

    我想知道当文本被文本视图的框架包裹时 是否有任何分隔符可以用来识别文本是否被包裹 例如 如果我的文本视图的宽度为 50 px 并且文本超过该宽度 则会将文本换行到下一行 我想计算文本视图中的行数 现在 n 和 r 对我没有帮助 我的代码是
  • 如何使用私钥将 .pfx 文件转换为密钥库?

    我需要签署 Android 应用程序 apk I have pfx文件 我把它转换为 cer通过 Internet Explorer 文件然后转换 cer to keystore使用密钥工具 然后我尝试签名 apk与 jarsigner 但
  • Spring Boot - 处理 NoHandlerFoundException

    阅读关于如何处理 NoHandlerFoundException 的 Spring 参考指南发现Spring默认设置 throwExceptionIfNoHandlerFound to false 知道了这一点 我认为将此参数设置为一个好主
  • NSWindow 可恢复并不总是有效

    我已经检查了 NSWindow 上的可恢复选项 当我移动应用程序并更改其大小并关闭 重新打开应用程序时 它将窗口大小和位置设置为最后的大小和位置 但这并不是在我测试的每台计算机上都会发生 它只发生在少数计算机上 他们没有关于简历的特殊设置
  • C# - 类的通用 HashCode 实现

    我正在研究如何为一个类构建最好的哈希码 我看到了一些算法 我看到了这个 哈希码实现 似乎 NET类的HashCode方法是类似的 通过反映代码来查看 所以问题是 为什么不创建上面的静态类来自动构建 HashCode 只需传递我们视为 键 的
  • vim 中可以对一组行进行排序吗?

    据我所知 vim 的 sort 方法会对每一行进行排序 我有一些代码以 3 行为一组 我该如何排序 请忽略那些糟糕的代码 它是一个遗留应用程序 我想按大小写 AF 行排序 但忽略 分组 国家 地区并换行 case AF country Af
  • 使用 Dagger 2 在库模块中注入应用程序上下文

    我正在构建一个具有一些功能的应用程序 ContentProvider SyncAdapter 作业服务和相关的持久性逻辑 在这些之上是带有 UI 的活动 我试图将所有上述功能放在一个单独的库模块中 因为理论上它们的逻辑是独立的并且可以由任何