代码之家  ›  专栏  ›  技术社区  ›  nyarian

为片段定义注入器时MVVM工厂中的Dagger2编译错误

  •  0
  • nyarian  · 技术社区  · 6 年前

    我有一个下一个根组件:

    @Singleton
    @Component(modules = [AndroidInjectionModule::class,
            AndroidSupportInjectionModule::class, 
            ActivityBuilderModule::class])
    interface RootComponent : AndroidInjector<DaggerApplication> {
        fun inject(myApplication: MyApplication)
        override fun inject(photoPartyApplication: DaggerApplication)
    
        @Component.Builder
        interface Builder {
            @BindsInstance
            fun application(application: Application): Builder
            fun build(): RootComponent
        }
    }
    

    在ActivityBuilder模块中:

    @Module
    abstract class ActivityBuilderModule {
    
        @ContributesAndroidInjector(modules = [MainActivityModule::class,
                ViewModelModule::class])
        @ActivityScope
        abstract fun bindMainActivity(): MainActivity
    
        @ContributesAndroidInjector(modules = [SecondaryActivityModule::class,
                ViewModelModule::class,
                FragmentBuilderModule::class])
        @ActivityScope
        abstract fun bindSecondaryActivity(): SecondaryActivity
    
    }
    

    ViewModelModule 是帮助在 ViewModel 类别和组成 @Binds 在特定实例和 视图模型 键入。

    MainActivityModule SecondaryActivityModule 为相应的活动定义特定的依赖关系。

    关键是当我加上这个 碎片构建模块 -编译开始发出错误。下面是堆栈跟踪:

    错误:[dagger/missingbinding]如果没有@inject构造函数或@provides带注释的方法,则无法提供某些\u package.specificdependency。

    公共抽象接口rootcomponent扩展了dagger.android.androidInjector{

    ^

    在组件中存在与匹配关键字的绑定:

    在某些包mainViewModel(specificdependency,)中注入了一些包.specificdependency。

    某些包mainViewModel被注入到某些包的viewmodelmodule.mainViewModel(viewmodel)

    Map<Class<? extends ViewModel>, Provider<ViewModel>> is injected at
          some_package.ViewModelFactory(viewModelProviders)
    

    在某些包中注入了某些包.viewmodelmodule.bindviewmodelmfactory(工厂)

    android.arch.lifecycle.viewmodelprovider.factory被注入到一些

    在dagger.android.androidinjector.inject(t)处注入了一些_package.myfragment

    [一些程序包.rootcomponent一些程序包.activitybuildermodule一些bindsecondaryactivity.secondaryactivitysubcomponent一些程序包.fragmentbuildermodule提供myfragmentfactorymyfragmentsubcomponent]

    据我所知,Dagger假设必须为 map 属于 Class<? extends ViewModel> -> Provider<ViewModel> ,如果有的话 ViewModels 陷入 factory ,而且 工厂 注入到组件中,则如果组件将要求 任何 viewmodel 我是说, 必须送过去 是的。为了把所有的 viewmodels ,同样,所有依赖项都必须可用(这不是真的,因为 MainViewModel 只能从 MainModule ,这就是匕首在堆栈跟踪之前所说的)。

    是否有解决方法来提供对 地图 属于 类<?扩展ViewModel>->提供程序<ViewModel> 按需而不是在编译时构建整个图(这会导致编译时错误)

    1 回复  |  直到 6 年前
        1
  •  0
  •   Shweta Chauhan    6 年前

    首先在rootcomponent中添加viewmodelmodule

     @Singleton
     @Component(modules = [AndroidInjectionModule::class,
                AndroidSupportInjectionModule::class, 
                ActivityBuilderModule::class,
                ViewModelModule::class])                 // add this so you don't have to add for every activity
        interface RootComponent : AndroidInjector<DaggerApplication> {
            fun inject(myApplication: MyApplication)
            override fun inject(photoPartyApplication: DaggerApplication)
    
            @Component.Builder
            interface Builder {
                @BindsInstance
                fun application(application: Application): Builder
                fun build(): RootComponent
            }
        }
    

    现在在activitybuildermodule中只添加activty

     @Module
     abstract class ActivityBuilderModule {
    
        @ContributesAndroidInjector
        @ActivityScope
        abstract fun bindMainActivity(): MainActivity
     }
    

    现在在ViewModel模块中添加所有ViewModel

     @Module
     abstract class ViewModelModule {
    
        @Binds
        @IntoMap
        @ViewModelKey(MainActivityModule::class)
        abstract fun bindMainActivityViewModel(mainActivityViewModel: MainActivityModule): ViewModel
    }
    

    添加ViewModelKey

     @MustBeDocumented
     @kotlin.annotation.Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
     @kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
     @MapKey
     internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
    

    和ViewModelFactory

    @Singleton
    class KotlinViewModelFactory @Inject
    constructor(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory {
    
        @Suppress("UNCHECKED_CAST")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            var creator: Provider<out ViewModel>? = creators[modelClass]
            if (creator == null) {
                for ((key, value) in creators) {
                    if (modelClass.isAssignableFrom(key)) {
                        creator = value
                        break
                    }
                }
            }
            if (creator == null) {
                throw IllegalArgumentException("unknown model class $modelClass")
            }
            try {
                Timber.d(creator.toString())
                return creator.get() as T
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }