Есть два фрагмента: ParentFragment и ChildFragment.
ChildFragment был добавлен в список ParentFragment.
Теперь с помощью Dagger2 для Android есть ParentFragmentModule с методом:
@Provides
fun provideViewModel(fragment: ParentFragment, myViewModelFactory: MyViewModelFactory): MyViewModel {
return ViewModelProviders.of(fragment, myViewModelFactory).get(MyViewModelImpl::class.java)
}
Где MyViewModelFactory, MyViewModel, MyViewModelImpl - это простая логика ViewModel, созданная в приложении.
И у ChildFragmentModule есть метод:
@Provides
fun provideViewModel(fragment: ChildFragment, myViewModelFactory: MyViewModelFactory): MyViewModel {
return ViewModelProviders.of(fragment, myViewModelFactory).get(MyViewModelImpl::class.java)
}
Это, очевидно, создает два отдельных экземпляра ViewModel, поскольку они получают два разных экземпляра фрагмента.
Как сделать так, чтобы он возвращал один и тот же экземпляр, чтобы данные могли совместно использоваться как родительским, так и дочерним фрагментами?
Я попытался передать ParentFragment вместо ChildFragment в ChildFragmentModule, но это привело к ошибке внедрения зависимости Dagger.
Создайте свой ViewModel с помощью прицела Activity. Тогда все Fragment в этом Activity получат один и тот же экземпляр ViewModel.
Проверьте официальную ссылку ViewModelProviders. Вы можете создать ViewModel как с прицелом Activity, так и с Fragment.
ViewModelProvider of (FragmentActivity activity)
Creates a ViewModelProvider, which retains ViewModels while a scope of given Activity is alive. More detailed explanation is in ViewModel.
а также
ViewModelProvider of (Fragment fragment)
Creates a ViewModelProvider, which retains ViewModels while a scope of given fragment is alive. More detailed explanation is in ViewModel.
Пример кода для создания ViewModel
Из активности:
movieListViewModel = ViewModelProviders.of(this).get(MovieListViewModel.class);
Из фрагмента:
movieListViewModel = ViewModelProviders.of(getActivity()).get(MovieListViewModel.class);
Спасибо. Это работает гладко! Просто для ознакомления, области видимости родительского и дочернего фрагментов работают одновременно. Как добиться того же без использования Activity?
Как поделиться movieListViewModel с другим модулем? Это возможно
А как насчет подхода единой деятельности? Нецелесообразно связывать все модели общего представления с одним действием.
просто модификация, чтобы избежать исключения NullPointerException movieListViewModel = ViewModelProviders.of (requireActivity ()). get (MovieListViewMo del.class);
Чтобы добавить к этому, можно ли получить модель представления для отдельного действия для отправки данных в дочерний фрагмент MainActivity?
Используя Фрагмент-ktx, мы можем сделать как In **ParentFragment**
private val viewModel: DemoViewModel by viewModels()
А также
In ChildFragment
private val viewModel: DemoViewModel by viewModels(
ownerProducer = { requireParentFragment() }
)
Делая это, мы можем получить тот же экземпляр ViewModel в Родительский фрагмент и Детский фрагмент
добавить зависимости в приложение -> build.gralde
implementation 'androidx.fragment:fragment-ktx:1.1.0
Реализуйте фрагмент-ktx в своем приложение -> build.gradle:
implementation 'androidx.fragment:fragment-ktx:1.2.5
Если вы используете компонент навигации (https://developer.android.com/guide/navigation)
В parentFragment вы можете получить viewModel следующим образом:
private val viewModel by viewModels<DemoViewModel>()
И затем, когда вам понадобится этот viewModel в childFragment, вы можете получить его следующим образом:
private val viewModel by viewModels<DemoViewModel>({requireGrandParentFragment()})
requireGrandParentFragment () - это настраиваемое расширение фрагмента:
fun Fragment.requireGrandParentFragment() = this.requireParentFragment().requireParentFragment()
Если вы не используете компонент навигации
вы можете получить к нему доступ так:
private val viewModel by viewModels<DemoViewModel>({requireParentFragment()})
У меня такая же проблема, как и все решение, но не работающая в моем сценарии, я предлагаю другое решение с использованием requireParentFragment () return NavHostFragment в дочернем фрагменте, решите его, используя
private val viewModel: childViewModel by viewModels(
ownerProducer = { requireParentFragment().childFragmentManager.primaryNavigationFragment!! }
)
в Parent Fragmet используйте это
private val viewModel: MyOrdersVM by viewModels()
см. developer.android.com/topic/libraries/architecture/…