草庐IT

android - Dagger:组件中存在具有匹配键的绑定(bind)

coder 2023-12-26 原文

我正在使用 Dagger 2.16 并关注 this我的 Dagger 实现的文章。在我只有一个 Activity(HomeActivity) 之前,此实现一切正常。我一开始在 SplashScreenActivity 中实现 Dagger。我开始收到此错误。这是我项目中的一些代码

AppComponent.kt

@Singleton
@Component(modules = [
    AndroidInjectionModule::class,
    AppModule::class,
    ActivityBuilder::class,
    ServiceBuilder::class,
    BroadcastRecieverBuilder::class])
interface AppComponent : AndroidInjector<MyApp> {
    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}

AppModule.kt

@Module()
class AppModule {

    @Provides
    @Singleton
    fun provideContext(application: MyApp): Context {
        return application
    }

    @Provides
    @Singleton
    fun provideRestService(retrofit: Retrofit): RestService {
        return retrofit.create(RestService::class.java)
    }
    ...
}

ActivityBuilder.kt

@Module
abstract class ActivityBuilder {

    @ContributesAndroidInjector(modules = [HomeActivityModule::class])
    @PerActivity
    abstract fun bindHomeActivity(): HomeActivity

    @ContributesAndroidInjector(modules = [SplashScreenModule::class])
    @PerActivity
    abstract fun bindSplashActivity(): SplashScreenActivity
}

BaseActivity.kt

abstract class BaseActivity<V : BaseView, P : MvpBasePresenter<V>> :
        MvpActivity<V, P>(), BaseView, HasSupportFragmentInjector {
    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

    @Inject
    lateinit var mPresenter: P

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun createPresenter(): P = mPresenter

    override fun supportFragmentInjector(): AndroidInjector<Fragment> {
        return fragmentInjector
    }
}

我有自己的 BaseActivity 而不是 DaggerActivity,因为我要从 mosby 的 MvpActivity 继承。

SplashScreenModule.kt

@Module
abstract class SplashScreenModule {

    @Binds
    @PerActivity
    internal abstract fun splashPresenter(splashPresenter: SplashScreenPresenter): BasePresenter<*>
}

HomeActivityModule.kt

@Module
abstract class HomeActivityModule {

    @Binds
    @PerActivity
    internal abstract fun homePresenter(homePresenter: HomeActivityPresenter): BasePresenter<*>

    @ContributesAndroidInjector(modules = [DownloadFragmentModule::class])
    @PerFragment
    internal abstract fun downloadsFragment(): DownloadsFragment
}

现在当我构建它时,出现如下错误

error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.realtime.app.MyApp> {
                ^
  A binding with matching key exists in component: com.realtime.dagger.ActivityBuilder_BindHomeActivity.HomeActivitySubcomponent
      java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> is injected at
          dagger.android.DispatchingAndroidInjector.<init>(injectorFactories)
      dagger.android.DispatchingAndroidInjector<android.support.v4.app.Fragment> is injected at
          com.realtime.core.BaseActivity.fragmentInjector
      com.realtime.splashScreen.SplashScreenActivity is injected at
          dagger.android.AndroidInjector.inject(T)
  component path: com.realtime.dagger.AppComponent → com.realtime.dagger.ActivityBuilder_BindSplashActivity.SplashScreenActivitySubcomponent

我已经经历过其他类似的问题,例如 this但无法将其与我所面临的联系起来。我错过了什么?

更新:目前我没有在 SplashScreenActivity 中继承 BaseActivity,这样我就可以避免注入(inject) fragmentInjector: DispatchingAndroidInjector<Fragment> .它目前正在工作,因为我在 SplashScreenActivity 中没有任何 fragment 。

最佳答案

它适用于 HomeActivity,因为它绑定(bind)了一个 fragment :

@ContributesAndroidInjector
fun downloadsFragment(): DownloadsFragment

SplashScreenActivity 没有。


AndroidInjection 使用 DispatchingAndroidInjector 来处理运行时注入(inject),它基本上包含类的 Map 到它们的组件构建器。需要像其他所有内容一样注入(inject)此 map 。在 HomeActivity 的情况下,模块中的 fragment 声明为 map 生成一个绑定(bind),然后可以将其注入(inject)。

由于启动 Activity 上没有 fragment ,因此 Dagger 不知道任何绑定(bind),更不用说任何 map 了。这就是为什么它提示它 cannot be provided .

您可以阅读更多here about multibindings .

为防止这种情况发生,您应该注册 AndroidInjectionModule在您的 AppComponent 上,它只包含空 map 的声明。

虽然它包含 android.app.Fragment 的声明,但它不包含 android.support.v4.app.Fragment 的声明,这就是错误的来源。


因此,要修复此特定错误,您应该添加 AndroidSupportInjectionModule到您的组件,其中还包括支持绑定(bind),当 Activity 中没有 fragment 时提供一个空映射。

@Component(modules = [AndroidSupportInjectionModule::class, /* ... */])
interface AppComponent { /* ... */ }

关于android - Dagger:组件中存在具有匹配键的绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50321116/

有关android - Dagger:组件中存在具有匹配键的绑定(bind)的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  3. ruby - 匹配未转义的平衡定界符对 - 2

    如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。

  4. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  5. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  6. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  7. ruby - 匹配大写字母并用后续字母填充,直到一定的字符串长度 - 2

    我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种

  8. ruby-on-rails - Rails 3.1 中具有相同形式的多个模型? - 2

    我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#

  9. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  10. ruby-on-rails - rspec - 如何检查方法是否存在? - 2

    我的模型有defself.empty_building//stuffend我怎样才能对这个现有的进行rspec?,已经尝试过:describe"empty_building"dosubject{Building.new}it{shouldrespond_to:empty_building}endbutgetting:Failure/Error:it{shouldrespond_to:empty_building}expected#torespondto:empty_building 最佳答案 你有一个类方法self.empty_bu

随机推荐