Dagger 2 在多个实例中单例

2023-11-23

我刚刚测试了 Dagger 2,并且在单例注释方面出现了一些奇怪的行为。我创建了一些测试代码来显示我的问题。

我的模块:

@Module
public class App {

    @Provides
    @Singleton
    ThingA provideThingA(){
        return new ConcreteThingA();
    }

}

我想要的单例接口:

public interface ThingA {
    void showMyId();
}

执行:

public class ConcreteThingA implements ThingA {
    @Override
    public void showMyId() {
        System.out.println(this);
    }
}

执行Dagger的代码:

public void doStuff() {
    ThingA thingA=DaggerThingAComponent.create().provideThingA();
    ThingA thingB=DaggerThingAComponent.create().provideThingA();
    System.out.println("Hello");
}

这是一个屏幕截图,显示当我请求两次时我没有得到相同的实例。我是否错过了一些基本的东西? ThingA 只是一个愚蠢的名字,在我的实际应用程序中,我希望在我的服务上有这种单例行为。

Debug screenshot


诀窍在于 Dagger 通过组件强制执行范围/生命周期,并且您在此处创建了两个单独的组件:

ThingA thingA = DaggerThingAComponent.create().provideThingA();
ThingA thingB = DaggerThingAComponent.create().provideThingA();

每次创建新的顶级 @Singleton 注解组件时,Dagger 都会为每个 @Singleton 对象创建一个全新的对象图,其中包含一个全新的容器。你应该用这个代替:

ThingAComponent component = DaggerThingAComponent.create();
ThingA thingA = component.provideThingA();
ThingA thingB = component.provideThingA();  // thingA == thingB

当然,通过依赖关系图进一步访问的任何内容都来自同一组件,因此这将保留您正在寻找的单例行为。


在大多数情况下,您不需要传递组件:组件应该用于顶级组件,并且通过注入器可访问的任何内容都应该@Inject其依赖项(这意味着它不需要对组件本身的引用) )。在迁移到 DI 或 Dagger 期间这可能会出现问题,但创建多个 @Singleton 组件并不是解决这个问题的方法。相反,请尝试以下操作之一:

  • 如果您需要某物的多个实例,您可以随时注入Provider<T>代替T无论您是否创建了@Provides方法。为此,您可以注入一个Lazy<T>如果您只需要特定依赖项的零个或一个副本,特别是如果该对象的创建特别繁重。
  • 如果您需要在对象图深处需要它,您可以 @Inject 组件本身,尽管它总是更好@Inject Provider<T> tProvider代替@Inject YourComponent只是打电话YourComponent.getT.
  • 在某些情况下,包括 Android,将组件保存到全局可访问的字段可能是有意义的,可以作为应用程序中的实例字段,也可以作为其他位置的静态字段。这具体是因为 Android 自己反射性地创建对象,而不是从图中获取注入的实例。对于所有其他情况,请注入依赖项以避免需要传递组件。

也可以看看:图中的绑定来自 Dagger 2 用户指南

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

Dagger 2 在多个实例中单例 的相关文章

  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • Java EE:如何获取我的应用程序的 URL?

    在 Java EE 中 如何动态检索应用程序的完整 URL 例如 如果 URL 是 localhost 8080 myapplication 我想要一个可以简单地将其作为字符串或其他形式返回给我的方法 我正在运行 GlassFish 作为应
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 从 127.0.0.1 到 2130706433,然后再返回

    使用标准 Java 库 从 IPV4 地址的点分字符串表示形式获取的最快方法是什么 127 0 0 1 到等效的整数表示 2130706433 相应地 反转所述操作的最快方法是什么 从整数开始2130706433到字符串表示形式 127 0
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 在两个活动之间传输数据[重复]

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

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • 在 Mac 上正确运行基于 SWT 的跨平台 jar

    我一直致力于一个基于 SWT 的项目 该项目旨在部署为 Java Web Start 从而可以在多个平台上使用 到目前为止 我已经成功解决了由于 SWT 依赖的系统特定库而出现的导出问题 请参阅相关thread https stackove
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • 捕获的图像分辨率太大

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

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • Google 查看器经常打开空白页

    Why Google Viewer有时是打开空白页而不是打开 PDF 文件 我可以使用模拟它this代码 并不是每次都会发生 需要单击谷歌浏览器按钮几次 我可以在 Edge 和 Chrome 上模拟它 请注意选项卡标题 Sem titlul
  • 空cocos2d 2.0(iPhone)中编译错误

    当我尝试在 xcode4 中编译新的 cocos2d box2d 项目时 我收到如下错误消息 Users bla bla Cocos2d 测试 Cocos2d 测试 libs cocos2d CCDirector h 32 9 致命错误 找
  • 使用 Java EE API 替换已弃用的 JPMS 模块

    Java 9 弃用了六个包含 Java EE API 的模块他们是将被删除 soon java activation with javax activation package java corba with javax activity
  • 在一行中创建并传递表值参数

    使用 SQL Server 2012 是否可以无需声明表值参数 TVP 只需将其传递到存储过程中 下面是一个非常简单的存储过程 SP 示例 它采用 TVP 和执行该 SP 的工作示例 其中我必须声明 TVP 填充它 然后将其传递到 SP 我
  • 最好的开源 Java 图表库是什么? (jfreechart 除外)[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 为什么没有更多易于使用的
  • Java 错误 - 软件导致连接中止:recv 失败

    完整的错误是 java net SocketException Software caused connection abort recv failed at java net SocketInputStream socketRead0 N
  • Node.js - 单线程,非阻塞?

    我正在学习 Node js 并且我读到 Node js 是单线程且非阻塞的 我有很好的 JavaScript 背景 并且确实了解回调 但我不太了解 Node js 如何成为单线程并在后台运行代码 这不是很矛盾吗 因为如果 Node js 是
  • PowerShell 脚本错误:字符串缺少终止符:

    非常简单的powershell脚本 Server side storage copy SourceStorageAccount myStorageAccount SourceStorageKey myKey SourceStorageCon
  • 如何解决上传项目到 GitHub 时“拒绝合并不相关历史记录”的问题?

    我已经安装了GitHub 桌面版和 Windows 机器上的 Git 我有一个 GitHub 帐户并创建了一个虚拟存储库 当我打算通过以下方式上传我的包裹时Git Bash命令行 它失败并出现错误 fatal refusing to mer
  • 有哪些好的科技播客?

    Locked 这个问题及其答案是locked因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 是的 播客 那些我可以在上班路上听的好听的小有声读物 就目前的播客数量而言 这就像大海捞针一样 只不过大海捞针恰好是互联网 并且充
  • $_GLOBAL 、 $_POST 等全局变量存储在哪里?

    我参加面试的时候 面试官问了我这个问题 他们使用的是堆 堆栈等内存 我用谷歌搜索但没有得到任何明确的答案 好吧 既然你标记了C 我就从这个开始吧 在 C 运行时中 全局变量存储在两个位置之一 数据段或BSS段 确定某一特定变量属于哪一个变量
  • Recyclerview 在滚动期间更改项目

    我有一个 RecyclerView 每行都有一个播放按钮 文本视图和进度条 当单击播放按钮时必须播放我的 SD 卡中的音频并且必须进度条 问题是 当我向下滚动 recyclerview 时 会更改下一行中的进度条 这意味着我可以一次在屏幕上
  • Android AudioTrack 混合的示例代码

    我的资源文件夹中有两个 PCM 声音文件 我使用输入流并将它们转换为字节数组 然后我通过标准化并添加 music1 和 music2 来处理它们 并将其输出到字节数组输出 最后 放置输出数组并将其馈送到 AudioTrack 显然 我什么也
  • 当且仅当 Python 不存在时才安全地创建文件

    我希望根据该文件是否已存在来写入该文件 仅在该文件尚不存在时写入 实际上 我希望继续尝试文件 直到找到不存在的文件 以下代码显示了潜在攻击者可以插入符号链接的方法 如中所建议的这个帖子在文件测试和正在写入的文件之间 如果代码以足够高的权限运
  • 换位表会导致搜索不稳定吗

    我正在编写一个国际象棋引擎 最近添加了一个换位表 在运行一些测试时 我发现虽然搜索仍然返回相同的最佳移动 但移动的价值 对于最大化玩家来说有多好 波动 这是转置表的正常行为吗 我记得读到转置表可能会导致搜索不稳定 是这个意思吗 那么这是我的
  • 我在 python lambda 处理程序中找不到回调参数

    我正在学习 aws lambda lex 我发现了带有 node js 的咖啡机器人示例代码 Main handler in node js Route the incoming request based on intent The JS
  • 可以将 LPTSTR 转换为 BSTR 吗?

    将 LPTSTR 直接转换为 BSTR 是否合法 根据我的对BSTR的理解 直接将 LPTSTR 转换为 BSTR 将会留下损坏的长度前缀 示例代码明确指出字符串文字不能存储到 BSTR 任何人都可以帮我确认 LPTSTR LPCTSTR
  • Indy TIdHTTP 发布问题

    我在向亚马逊发帖时遇到问题SES使用 Indy 的 TIdHTTP 的服务 这是我正在使用的代码的示例 procedure TMainFrm btnAmazonSESClick Sender TObject var SSLHandler T
  • Python 中的信号处理程序和日志记录

    日志记录模块的文档说 如果您使用信号模块实现异步信号处理程序 则可能无法在此类处理程序中使用日志记录 这是因为线程模块中的锁实现并不总是可重入的 因此不能从此类信号处理程序中调用 这表明不应从信号处理程序直接或间接调用的代码中进行日志记录调
  • Dagger 2 在多个实例中单例

    我刚刚测试了 Dagger 2 并且在单例注释方面出现了一些奇怪的行为 我创建了一些测试代码来显示我的问题 我的模块 Module public class App Provides Singleton ThingA provideThin