Проблема при использовании нескольких экземпляров одного и того же фрагмента с одной и той же ViewModel в Viewpager

У меня есть фрагмент (FRAG1) с моделью представления (VM1). Я создаю два новых экземпляра этого фрагмента в FragmentPagerAdapter для загрузки внутри ViewPager.

Viewpager присутствует внутри родительского фрагмента.

ViewModels в обоих экземплярах фрагмента не кажутся уникальными. Оба экземпляра фрагмента, по-видимому, имеют свойства экземпляра ViewModel, созданного во втором фрагменте, который инициализируется последним.

private inner class ItDeclarationFragAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm)
{
    override fun getItem(position: Int): Fragment
    {
        return when (position)
        {
            0 -> ITDeclarationSummaryFragment.newInstance(false)
            1 -> ITDeclarationSummaryFragment.newInstance(true)

            else -> ITDeclarationSummaryFragment.newInstance(false)
        }
    }

    override fun getCount(): Int
    {
        return 2
    }

    override fun getPageTitle(position: Int): CharSequence?
    {
        return when (position)
        {
            0 -> resources.getString(R.string.zpl_itDeclaration_tile)
            1 -> resources.getString(R.string.zpl_itDeclaration_poi_title)

            else -> resources.getString(R.string.zpl_reimbursements_summary)
        }
    }
}

Фрагмент создает новый экземпляр ViewModel в OnCreate().

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

    vm = ViewModelProvider.AndroidViewModelFactory.getInstance(activity!!.application).create(ITDeclarationSummaryViewModel::class.java)
    vm.setRepository(getRepo())
    vm.mIsPOI = arguments!![StringConstants.isPOI]!! as Boolean
}

Позже для него устанавливается значение Binding для OnCreateView().

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
    mView = inflater.inflate(R.layout.declaration_summary_fragment, container, false)

    mBinding       = DeclarationSummaryFragmentBinding.bind(mView!!)
    mBinding.model = vm
    mBinding.setLifecycleOwner(this)

    return mBinding.root
}

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

Например,

В модели представления есть логическое значение, которое имеет значение FALSE в первой ViewModel и TRUE во второй. Но как только будет создана вторая виртуальная машина, обе модели представления фрагментов будут TRUE.

Точно так же не работают наблюдатели LiveData в первой ViewModel.

Пожалуйста, помогите мне решить эту проблему. Заранее спасибо.


person Hariharan Ayyasamy    schedule 06.09.2018    source источник


Ответы (2)


Дело в том, что вы создаете ViewModels с AndroidViewModelFactory, который содержит один и тот же экземпляр для всех моделей представления, если вы используете одну и ту же модель представления во всех фрагментах. Возможно, рассмотрите возможность создания моделей представления, позвонив:

ViewModelProviders.of(fragment).get(ViewModel.class)

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

person mmmatey    schedule 06.09.2018
comment
Это подчеркивает идею масштаба ваших ViewModels. Насколько я понимаю, Владелец, которого вы передаете, в данном случае фрагмент, определяет жизненный цикл этой ViewModel. У меня была очень похожая проблема с использованием Viewpager с фрагментами. Первоначально я создаю одну большую модель представления, содержащую данные каждого фрагмента, но область представления модели для каждого фрагмента, как указано выше, делает дизайн намного более чистым, особенно для очистки после уничтожения фрагментов. - person Eurospoofer; 22.08.2019
comment
решил мою проблему спасибо - person Arjun Verma; 09.08.2021

Проблема не в модели фрагмента или представления.

Модели представления содержат экземпляр или класс репозитория. Я по ошибке предоставил один и тот же экземпляр класса Repository для обеих ViewModels.

Это приводило к тому, что данные сохранялись в ViewModels.

person Hariharan Ayyasamy    schedule 07.09.2018
comment
Можете ли вы помочь мне в этом случае, я также использую один и тот же фрагмент для 5 вкладок. У меня проблема в том, что изменение значения первого фрагмента отражает весь живой фрагмент, потому что я использую fragmentStatePagerAdapter. Я использую Кейтлин с mvvm. Можете ли вы предложить какое-то решение для обновления всех значений живых фрагментов. Спасибо - person Sumit Kumar; 20.01.2019
comment
Я думаю, что это не имеет ничего общего с FragmentAdapter или архитектурой. Моя проблема заключалась в том, что я предоставлял данные всем фрагментам, используя один и тот же экземпляр репозитория. Как только я создал новый экземпляр репо для каждого фрагмента, проблема была решена. Пожалуйста, опубликуйте код, чтобы я мог вам помочь. - person Hariharan Ayyasamy; 21.01.2019