Kodein - получить родительский фрагмент ViewModel - PullRequest
0 голосов
/ 12 апреля 2020

Я работаю над Android, но я думаю, что концепция будет одинаковой на всех платформах.

У меня есть фрагмент A, содержащий другой фрагмент B, использующий NavHostFragment.

Я могу легко извлечь ViewModel из фрагмента A:

class FragmentA : Fragment(), KodeinAware {

    protected val parentKodein by closestKodein()
    override val kodeinContext = kcontext<Fragment>(this)

    override val kodein: Kodein = Kodein.lazy {
        extend(parentKodein)
        import(myViewModelModule)
    }

    private val myViewModel: MyViewModel by instance()
}

Модуль также прост:

val myViewModelModule = Kodein.Module(TAG) {

    bind<MyViewModel>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
        ViewModelProvider(
            this.context,
            MyViewModelFactory(instance())
        ).get(
            MyViewModel::class.java
        )
    }

    bind<AMapper>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
        AMapper()
    }
}

Но я понятия не имею, как получить то же самое Экземпляр MyViewModel во фрагменте B, ближайший кодейн - это активность ...

Насколько я понимаю, мне нужно сделать что-то вроде

class FragmentB : Fragment(), KodeinAware {

    override val kodeinContext = kcontext<Fragment>(this)

    override val kodein: Kodein = Kodein.lazy {
        extend(fragmentAKodein)
    }

    private val myViewModel: MyViewModel by instance()
}

Но я понятия не имею, как получить фрагмент Kodein.

Большое спасибо

Редактировать:

Это то, что я закончил делать:

class FragmentA : Fragment(), KodeinAware {

    protected val parentKodein by closestKodein()

    override val kodeinContext: KodeinContext<Fragment> by lazy { kcontext(childFragmentManager.findFragmentById(R.id.nav_host_containing_fragment_B) as Fragment)
    }

    override val kodein: Kodein = Kodein.lazy {
        extend(parentKodein)
        import(myViewModelModule)
    }

    private val myViewModel: MyViewModel by instance()
}

val myViewModelModule = Kodein.Module(TAG) {

    bind<MyViewModel>() with scoped<BaseFragment>(AndroidLifecycleScope).singleton {
        ViewModelProvider(
            context.kodeinContext.value,
            MyViewModelFactory(
                instance()
            )
        ).get(
            MyViewModel::class.java
        )
    }

    bind<AMapper>() with scoped<Fragment>(AndroidLifecycleScope).singleton {
        AMapper()
    }
}

class FragmentB : Fragment(), KodeinAware {

    override val kodeinContext: KodeinContext<Fragment> by lazy {
        kcontext(parentFragment as Fragment)
    }

    override val kodein: Kodein = Kodein.lazy {
        extend(fragmentAKodein)
    }

    private val myViewModel: MyViewModel by instance()
}

Благодаря ViewModelFactory, то же самое экземпляр MyViewModel является общим для всех фрагментов.

Но это обходной путь, так как Кодейн не считает, что маппер находится в той же области видимости, и создает новый экземпляр для каждого фрагмента ...

1 Ответ

0 голосов
/ 14 апреля 2020

Использование настраиваемой области решило мою проблему: https://github.com/Kodein-Framework/Kodein-DI/issues/258

...