Я начал внедрять MVVM, и я не знаю, является ли использование ViewModel внутри моего Adapter хорошей практикой или антипаттерном.
В качестве примера представьте себе список цветов и изображение, в котором вы будете менять фон. В этом случае я наблюдаю за выбранным цветом и привязываю цвет фона для отображения в пользовательском интерфейсе.
Но я наблюдаю за colorSelected в двух местах:
Fragment для изменения цвета фонаAdapter для отображения какой цвет выбранИтак, правильно ли я использую MVVM, когда передаю и наблюдаю за ViewModel на Adapter?
вроде бы, но меня это не устраивает, я знаю, что если я добавлю сюда, никто не предложит решение. У тебя есть решение?
Я не уверен, что это хороший шаблон, но с этим есть одна проблема: таким образом ваш адаптер привязан к вашей ViewModel, что означает, что вы не можете повторно использовать его с другой ViewModel на другом экране. С другой стороны, гораздо проще работать без этих дополнительных обратных вызовов от recyclerView, которые упрощают реализацию. Я думаю, что «лучше» использовать обратные вызовы, но «проще» передать ViewModel (я думаю, CG должна справиться с этим без проблем)
когда вы сказали: «Сейчас я не уверен», это потому, что вы ищете лучший ответ?
Кстати спасибо
@AndroidStorm Я тоже искал ответ, но основная причина в том, что один программист скажет, что лучше сделать код более эластичным, увеличив объем работы, а другой скажет: «Зачем мне делать более эластичный код, если для этого требуется гораздо больше работы? ". Думаю, это зависит от проекта :)
Я только что нашел статью, в которой говорится, что что-то вроде Recyclerview - это представление, не имеющее никакого отношения к вашему проекту. Поэтому в нем не должно быть ссылки на ваши модели. Но все еще ищу правильный ответ.
@AndroidStorm Я использовал несколько шаблонов, думаю, ни один из них не является неправильным. Вопрос выбора. На данный момент я передаю интерфейс для обратного вызова адаптера, и таким образом я могу повторно использовать адаптер на нескольких экранах. Я могу расширить интерфейс в Fragment или ViewModel (так что я могу также передать ViewModel в конструкторе). Я использую это плюс привязку данных и отлично работает - например, я хочу "лайкнуть" пост - интерфейс использует обратный вызов, чтобы сообщить об этом фрагменту, фрагмент позволяет обработать вызов ViewModel, а из вызова я меняю информацию о модели поста (количество лайков и т. д.) И это отражается с помощью привязки данных в адаптере
Что ж, я искал решение этого вопроса, но, наконец, должен справиться сам. Я хотел бы разместить здесь свою мысль для обсуждения.
Проще говоря, передача экземпляра viewModel адаптеру, на мой взгляд, не изящна. Вместо этого я рекомендую вам переопределите метод onAttachedToRecyclerView вашего RecyclerViewAdapter, чтобы получить вашу модель просмотра:
public class YoursAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
......
private YoursViewModel viewModel;
......
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
if (viewModel==null){
viewModel=new ViewModelProvider((ViewModelStoreOwner) recyclerView.getContext()).get(YoursViewModel.class);
}
}
......
}
Почему я считаю это решение хорошим?
1. Сама модель ViewModel не имеет ничего общего с контекстами. Но для создания экземпляра ViewModel нужен контекст.
2 、 Какой контекст вы выберете? Контекст recyclerView, поскольку вы хотите что-то сделать внутри адаптера, а адаптер связан с recyclerView. Почему я переопределяю onAttachedToRecyclerView? Поскольку этот обратный вызов предоставляет ссылку recyclerView и выполняется только один раз.
3. Пока контекст recyclerView жив, ViewModel жив. Это то, что ты хочешь? Если ответ «Да», то разумно создать экземпляр ViewModel на основе контекста recyclerView.
4. У вас есть ViewModel во фрагменте. Разумно ли в адаптере создавать новую? Да. Одно из преимуществ ViewModel - обмен данными, пока они занимаются одной и той же деятельностью.
5. На самом деле вам не нужно наблюдать за живыми данными внутри адаптера (который снова требует контекста), если вы правильно спроектировали ViewModel. В основном вы просто наблюдаете живые данные на фрагменте. Ваша ViewModel внутри адаптера просто отвечает за изменение данных, не заботясь о том, как данные изменились, то есть делать yourViewModelInstance.post_value_to_liveData_and return_it().observe() на фрагменте и делать yourViewModelInstance.post_value_to_liveData_and return_it() внутри адаптера.
вы нашли эффективное решение своей проблемы?