Dagger 2:如何从 FragmentFactory 的子组件绑定父组件中的 Fragment Map

2024-05-07

我有这个 Dagger 2 配置:

应用程序组件.kt

@Singleton
@Component(
    modules = [
        AndroidSupportInjectionModule::class,
        AppModule::class,
        ActivityBindingModule::class,
    ]
)
interface AppComponent : AndroidInjector<AppApplication> {
    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<AppApplication>()
}

ActivityBindingModule.kt

@Module
abstract class ActivityBindingModule {
    @ActivityScoped
    @ContributesAndroidInjector(
        modules = [
            MainActivityModule::class,
            FragmentModule::class //a fragment factory for each activity
        ]
    )
    internal abstract fun mainActivity(): MainActivity
}

MainActivityModule.kt

@Module(subcomponents = [LoginFragmentSubcomponent::class])
abstract class MainActivityModule {
    //uncommenting this works fine but Fragment can't be scoped
    //@Binds
    //@IntoMap
    //@FragmentKey(LoginFragment::class)
    //abstract fun bindLoginFragment(loginFragment: LoginFragment): Fragment

    //...other things which work fine
}

@Subcomponent(modules = [LoginFragmentModule::class])
@FragmentScoped
interface LoginFragmentSubcomponent : AndroidInjector<LoginFragment> {
    @Subcomponent.Builder
    abstract class Builder : AndroidInjector.Builder<LoginFragment>()
}

@Module
abstract class LoginFragmentModule {
    //this can't be seen from Map used in DefaultFragmentFactory
    @Binds
    @IntoMap
    @FragmentKey(LoginFragment::class)
    abstract fun bindLoginFragment(loginFragment: LoginFragment): Fragment
}

片段模块.kt

@Module
abstract class FragmentModule {
    @Binds
    internal abstract fun bindFragmentFactory(factory: DefaultFragmentFactory): FragmentFactory
}

默认FragmentFactory.kt

@ActivityScoped
class DefaultFragmentFactory @Inject constructor(
    private val creators: Map<Class<out Fragment>, @JvmSuppressWildcards Provider<Fragment>>
) : FragmentFactory() {
    //this is deprecated in fragment-ktx 1.1.0-alpha06 
    //but you need to override this if you were using the bundle
    override fun instantiate(classLoader: ClassLoader, className: String, args: Bundle?): Fragment {
        return instantiate(classLoader, className).apply { arguments = args }
    }
    override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
        val fragmentClass = loadFragmentClass(classLoader, className)
        val found = creators.entries.find { fragmentClass.isAssignableFrom(it.key) }
        val provider = found?.value
        //if we don't find a match in the map, proceed with the default empty constructor
        return if (provider != null) {
            provider.get()
        } else {
            fragmentClass.newInstance()
        }
    }
}

我在这里想做的是使用FragmentFactory来创建Fragments。 如代码中所述,我可以取消注释此行:

@Binds
@IntoMap
@FragmentKey(LoginFragment::class)
abstract fun bindLoginFragment(loginFragment: LoginFragment): Fragment

并删除所有连接到LoginFragmentSubcomponent并且注射工作正常。

这种方法的问题是 Fragment 无法正确确定作用域,如果 Fragment 被销毁,下面的所有子 Fragments 都会被销毁,这将迫使 Factory 在下一次调用时创建一个新实例。

所以我决定添加一个Subcomponent调用 LoginFragmentSubcomponent 能够定义@FragmentScoped在上面。 现在的问题是从模块LoginFragmentModule我无法为父母做出贡献Map我需要在DefaultFragmentFactory其类型为:

Map<Class<out Fragment>, @JvmSuppressWildcards Provider<Fragment>>

事实上,我在编译时收到的错误是:

[Dagger/MissingBinding] 
java.util.Map<java.lang.Class<? extends androidx.fragment.app.Fragment>,
javax.inject.Provider<androidx.fragment.app.Fragment>> cannot be provided 
without an @Provides-annotated method.

这里有一个具有可重现问题的示例存储库: https://github.com/matpag/dagger-test-fragmentfactory https://github.com/matpag/dagger-test-fragmentfactory

有针对这个的解决方法吗?

使用匕首2.21

提前致谢

PS:这背后的想法FragmentFactory注射来自于此 很棒的帖子:https://www.captechconsulting.com/blogs/using-androidxs-fragmentfactory-with-dagger-for-fragment-dependency-injection https://www.captechconsulting.com/blogs/using-androidxs-fragmentfactory-with-dagger-for-fragment-dependency-injection我只是稍微调整了一下。


None

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

Dagger 2:如何从 FragmentFactory 的子组件绑定父组件中的 Fragment Map 的相关文章

随机推荐

  • WebSockets 监听 UNIX 域套接字?

    是否可以在 nginx 服务器后面设置一个 WebSockets 服务器来处理 UNIX 域套接字上的连接 我目前在同一台计算机上有多个 WebSocket 服务器实例 并且存在端口共享问题 所有实例都必须分配一个唯一的端口 我想避免这种情
  • 模块版本不匹配。预计49,实际48

    我正在使用 Electron 模块 mdns 并且收到此错误 A JavaScript error occurred in the main process Uncaught Exception Error Module version m
  • 阻止 Android 应用程序启动

    我读过很多关于是否可以阻止 Android 应用程序启动的问题 但所有答案似乎都是 不 你不能 这个想法非常简单 我们希望用户能够使用预装在其移动设备上的一组受限制的应用程序 如果用户尝试启动未经授权的应用程序 系统将提示他输入 PIN 码
  • 使用 cmd.exe 更改目录并在该目录中运行命令

    我想做的就是 更改到不同驱动器的特定目录 在该目录中运行命令 例如目录 我需要使用从不同驱动器开始的 cmd exe 在一行中执行此操作 我会这样做 c cd temp dir 所以到目前为止我在一份声明中 cmd c c cd temp
  • 角度守卫,文档中的声明不明确

    我想深入了解角度 所以我读了the docs http angular io这非常有帮助 现在我正在研究守卫 我在文档中读到了这个声明 路由器首先从最深的子路由到顶部检查 CanDeactivate 和 CanActivateChild 防
  • 在读取之前设置未定义的 javascript 属性

    var tr tr SomeThing SomeThingElse console log tr SomeThing SomeThingElse console log tr Other undefined tr get function
  • 同一张表上的多对多

    有趣的是我从来没有遇到过这个 我从来没有想过一个人可以在一张桌子上建立 多对多 关系 直到我开始开发一种用户可以互相 加好友 的系统 社交网络 标准查找表 至少以我习惯使用的方式 在这里不合适 让我们保持简单 用户表有 id 和 name
  • android-button 背景可绘制不起作用

    这是我的 xml 可绘制代码 名称为 bts theme xml
  • Android:如何在触摸事件中手动实现长按?

    简短版本 我想要一种方法来在 onTouchEvent 上启动基于时间的计数器 并测试在响应之前是否已经过了一定的时间 作为手动 LongTouch 检测 解释 我有一个自定义 imageView 可以通过两根手指滑动滑入 滑出屏幕 我想向
  • Angular 2 测试 - 获取 DOM 元素样式

    我想在 Angular 2 应用程序中测试隐藏显示按钮的功能 测试是用 Jasmine 编写的 所以我需要检查display相关元素的属性 我怎样才能使用 Angular 获得这个属性debugElement 测试代码 let input
  • 我不应该在 Spring Boot 项目中使用“new”关键字吗?

    我正在研究 Spring Boot Rest API 最后我确实使用了new关键字在这里和那里 我想知道 当我在程序中使用 new 关键字时 我是否做错了什么 而如果在实际项目中绝对禁止使用new关键字 如果答案是肯定的 我应该注释我编写的
  • C# 中多个类的别名

    我想 正在努力 使我的代码更具可读性 我一直在使用以下类别名 using Histogram EmpiricScore
  • 加载包时 R 会话中止

    我的 RStudio 0 99 879 R 3 2 3 OSX 10 11 3 崩溃R Session Aborted每次运行都会出现错误提示require ggvis v0 4 2 我已经重新安装了 R RStudio 和 ggvis 没
  • 多个 Rails 应用程序,单个 MySQL 数据库

    我打算为 site com api site com admin site com 分别创建多个 Rails 应用程序 所有应用程序都将从一个 MySQL 数据库访问相同的表 应用程序和数据库在同一服务器上运行 对于上述访问场景 Rails
  • 如何列出当前正在验证的拉取请求中更改的所有文件(在 VSTS 中)?

    我有一个 PR 验证版本 我想列出 PR 中更改的所有文件以及状态 源在每个构建上同步 因此 在合并 PR 更改之前 源位于修订版A 通常origin master 让我将 PR 合并提交指定为B 我当前的实现调用git diff tree
  • iPhone - SSL 连接

    学习通过 iPhone 连接 ssl Web 服务的最佳起点是什么 到目前为止 我通过 SOAP 等通过 http 进行了一些基本连接 但我没有使用 https 的经验 任何好的资源 教程 起始参考 use nsurl class 都值得赞
  • UIButton突出显示区域延伸到按钮之外

    当用户触摸 UIButton 时 应启动突出显示状态 当他将手指滑到按钮之外 仍然没有抬起手指 时 按钮突出显示应该停止 并且当他抬起手指时 不应触发按钮 这种行为正是 iOS 的工作原理 但我对仍然应用突出显示的有效区域感到有点惊讶 对于
  • AngularJS 服务位于单独的文件中

    我的 app js 包含 var app angular module myApp config routeProvider function routeProvider http 服务看起来像 app service MyService
  • Python 扩展方法

    好的 在 C 中我们有这样的东西 public static string Destroy this string s return 所以基本上 当你有一个字符串时 你可以这样做 str This is my string to be de
  • Dagger 2:如何从 FragmentFactory 的子组件绑定父组件中的 Fragment Map

    我有这个 Dagger 2 配置 应用程序组件 kt Singleton Component modules AndroidSupportInjectionModule class AppModule class ActivityBindi