Dagger2, tilsetning av et bindende for ViewModelProvider.Factory i en avhengig komponent

stemmer
0

Problemet

Ved forsøk på å legge til et ViewModelbind inn i multibinding for en arvelig ViewModelFactory(laget med ikke omfanget) innenfor en nedre ramme ( @FragmentScope), holder jeg denne feilen:

java.lang.IllegalArgumentException: ukjent modell klasse com.example.app.MyFragmentVM

Det jeg har lest eller prøvd

(Merk: nedenfor er ikke på noen måte en uttømmende liste, men er to gode eksempler på ressurser og hva slags råd jeg har lest gjennom)

Jeg er relativt ny til å jobbe med Dagger så jeg måtte gjøre en masse googling for å prøve å forstå hva som har foregått, men jeg har nådd et punkt der, til min forståelse, noe skal jobbe (?) .. .

Fra kilder som ligner på [1], jeg eliminert @Singletonomfang på ViewModelFactory, men jeg fortsatt få den nevnte ulykken sier at det er ingen modell klasse funnet i kartleggingen.

Fra kilder som ligner på [2] Jeg prøvde å forsterke min forståelse av hvordan avhengig jobbet og hvordan elementer er utsatt for avhengige komponenter. Jeg vet og forstår hvordan ViewModelProvider.Factoryer tilgjengelig for min MyFragmentComponentog det er relatert moduler.

Men jeg forstår ikke hvorfor det @Binds @IntoMapikke fungerer for MyFragmentVM.

Koden

La meg først gå gjennom oppsettet av ting som allerede finnes i programmet - nesten ingen av det var omfangs for konkrete saker

// AppComponent
@Component(modules=[AppModule::class, ViewModelModule::class])
interface AppComponent {
    fun viewModelFactory(): ViewModelProvider.Factory

    fun inject(activity: MainActivity)
    // ... and other injections
}

// AppModule
@Module
class AppModule {
    @Provides
    @Singleton
    fun providesSomething(): Something

    // a bunch of other providers for the various injection sites, all @Singleton scoped
}

// ViewModelModule
@Module
abstract class ViewModelModule {
    @Binds
    abstract fun bindsViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(MainActivityVM::class)
    abstract fun bindsMainActivityVM(vm: MainActivityVM): ViewModel
}

// VMFactory
class ViewModelFactory @Injects constructor(
    private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
): ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        val creator = creators[modelClass] ?: creators.entries.firstOrNull {
            modelClass.isAssignableFrom(it.key)
        }?.value ?: throw IllegalArgumentException(unknown model class $modelClass)

        try {
            @Suppress(UNCHECKED_CAST)
            return creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

Og følgende er hvordan jeg prøver å legge til og utnytte min @FragmentScope:

// MyFragmentComponent
@FragmentScope
@Component(
    dependencies = [AppComponent::class],
    modules = [MyFragmentModule::class, MyFragmentVMModule::class]
)
interface MyFragmentComponent {
    fun inject(fragment: MyFragment)
}

// MyFragmentModule
@Module
class MyFragmentModule {
    @Provides
    @FragmentScope
    fun providesVMDependency(): VMDependency {
        // ...
    }
}

// MyFragmentVMModule
@Module
abstract class MyFragmentVMModule {
    @Binds
    @IntoMap
    @ViewModelKey(MyFragmentVM::class)
    abstract fun bindsMyFragmentVM(vm: MyFragmentVM): ViewModel
}

// MyFragment
class MyFragment : Fragment() {
    @set:Inject
    internal lateinit var vmFactory: ViewModelProvider.Factory

    private lateinit var viewModel: MyFragmentVM

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        DaggerMyFragmentComponent.builder()
            .appComponent(MyApplication.instance.component)
            .build()
            .inject(this)

        viewModel = ViewModelProvider(this, vmFactory).get(MyFragmentVM::class.java)
    }
}

Hva er interessant her å merke seg er at MyFragmentModuleselv ikke ender opp med å gi noen unike injeksjoner for MyFragment(de alle kommer fra AppComponent som det er akkurat nå). Det gjør imidlertid gi unike injeksjoner for ViewModelat MyFragmentbruk.

Publisert på 19/03/2020 klokken 21:51
kilden bruker
På andre språk...                            

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more