Dagger2, добавление связывания для ViewModelProvider.Factory в зависимом компоненте

голоса
0

Проблема

При попытке добавить ViewModelпривязку в MultiBinding для наследственных ViewModelFactory(созданного без области) в нижних рамках ( @FragmentScope), я продолжаю нарваться этой ошибку:

java.lang.IllegalArgumentException: неизвестно модель класса com.example.app.MyFragmentVM

То, что я читал или пытался

(Примечание: ниже отнюдь не исчерпывающий список, но два примера хороших ресурсов и виды консультаций я просматривал)

Я относительно новый для работы с кинжалом, так что я должен был сделать много Googling, чтобы попытаться понять, что происходило, но я достиг точки, где, к моему пониманию, что-то должно работать (?) .. ,

Из источников , подобных [1], я устранил @Singletonсферу на ViewModelFactory, но я все еще получаю вышеупомянутые аварии говоря нет модели класса найден в отображении.

Из источников , подобных [2] Я пытался усилить свое понимание того , как зависимости работал и как элементы подвергаются зависимым компонентам. Я знаю и понимаю , как ViewModelProvider.Factoryэто доступно Мои MyFragmentComponentи это связано с модулями.

Однако я не понимаю , почему @Binds @IntoMapне работает для MyFragmentVM.

Код

Позвольте мне сначала пройти через настройки материала, который уже существует в приложении - почти ни одна из них не была областью действия для конкретных случаев

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

И следующее, как я пытаюсь добавить и использовать мой @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)
    }
}

Что здесь интересно отметить, что MyFragmentModuleсамо по себе не в конечном итоге предоставление каких - либо уникальных инъекций для MyFragment(те все приходят от AppComponent , как это прямо сейчас). Она тем не менее, обеспечивает уникальные инъекции для того, ViewModelчто MyFragmentиспользования.

Задан 19/03/2020 в 23:51
источник пользователем
На других языках...                            

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