Dagger2, Hinzufügen einer Bindung für ViewModelProvider.Factory in einer abhängigen Komponente

stimmen
0

Das Problem

Beim Versuch , eine hinzuzufügen ViewModelbinden in die mehrbindigen für eine vererbte ViewModelFactory(ohne Bereich erstellt) in einem geringeren Umfang ( @FragmentScope), ich in diesen Fehler nicht unterbrochen wird:

java.lang.IllegalArgumentException: unbekannt Modellklasse com.example.app.MyFragmentVM

Was ich habe gelesen, oder versucht,

(Anmerkung: die unten ist keineswegs eine erschöpfende Liste, sondern sind zwei gute Beispiele von Ressourcen und die Art der Rat, den ich durchgelesen habe)

Ich bin relativ neu mit Dolch zu arbeiten, damit ich viel Googeln zu tun hatte, um zu versuchen und zu verstehen, was ist los, aber ich habe einen Punkt erreicht, an dem, mein Verständnis soll etwas arbeiten (?) .. .

Von Quellen ähnlich wie [1], eliminierte ich den @SingletonUmfang auf ViewModelFactory, aber ich immer noch den oben genannten Crash bekommen sagt , gibt es keine Modellklasse in der Abbildung zu finden ist.

Von Quellen ähnlich wie [2] Ich habe versucht , mein Verständnis zu verstärken , wie Abhängigkeiten gearbeitet und wie Elemente werden in abhängigen Komponenten ausgesetzt. Ich weiß , und verstehen , wie ViewModelProvider.Factoryzu meiner Verfügung MyFragmentComponentund es ist im Zusammenhang Module.

Ich aber nicht verstehen , warum das @Binds @IntoMapnicht für die Arbeit MyFragmentVM.

Der Code

Lassen Sie mich gehen durch das Setup von dem Zeug ersten, die bereits in der Anwendung vorhanden ist - fast nichts davon wurde für bestimmte Fälle scoped

// 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)
        }
    }
}

Und die folgende ist, wie ich versuche, meinen @FragmentScope hinzuzufügen und zu nutzen:

// 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)
    }
}

Was hier zu Notiz interessant ist , dass MyFragmentModulesich nicht am Ende keine eindeutige Injektionen für die Bereitstellung MyFragment(alle von AppComponent kommen , wie es jetzt ist). Es macht jedoch bieten einzigartige Injektionen für die , ViewModeldass MyFragmentAnwendungen.

Veröffentlicht am 19/03/2020 um 21:51
quelle vom benutzer
In anderen Sprachen...                            

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