#android #архитектура
Допустим, есть RecyclerView с различными элементами ViewHolder. В одном типе элементов списка может быть семь виджетов EditText, в другом - другие компоненты. У каждого типа элементов своя логика валидации и прочее. Стандартное решение - вынести вьюхолдеры в отдельные классы, понятно. Тем не менее, в адаптере будет куча условий if, определяющих, как наполнить вьюхолдер данными, какой вьюхолдер создать для данного типа, и тд. Затем возникает проблема, что этот же элемент с его небольшой логикой валидации (допустим, что поле не должно начинаться с цифры и содержать меньше 8 символов), мне нужен на другом экране. Да, я могу переиспользовать вьюхолдер, но мне всё равно нужно повторять бойлерплейт с его инициализацией getItemViewType(), onCreateViewHolder()... Как же лучше организовать связку Адаптер-ВьюХолдер?
Ответы
Ответ 1
Посмотрите в сторону решения, описанного в http://hannesdorfmann.com/android/adapter-delegates. Там вводится новая сущность - AdapterDelegate. Делегат позволяет разгрузить ваши адаптеры и ViewHolder, а также сделать их максимально переиспользуемыми, если списков в приложении много. При этом во ViewHolder отсутсвует какая либо логика. Это просто класс-holder ссылок на View элементы (EditText и т.д.). В делегаты вы можете инжектить Презентеры, через которые провайдите действия пользователя. Однако бывают случаи, когда один элемент списка переиспользуется много где, и в этом элементе выполняется, например, "like". Инжектить Презентер бывает не очень удобно, так как тогда возникает дублирование кода и протягивание лишних зависимостей, чтобы в конце концов выполнить нужный пользовательский сценарий. Поэтому можно заинжектить в данный делегат специальный UseCase (Interactor), который как раз и выполняет пользовательский сценарий - нажатие на кнопку like.Ответ 2
Выносите ViewHolder из внутреннего и/или анонимного класса в публичный Используйте аннотации типа ButterKnife - здорово облегчают жизньОтвет 3
В своих проектах я использую эту библиотеку https://github.com/vivchar/RendererRecyclerViewAdapter Достаточно проста в использовании, поддерживает DiffUtil, Payloads, Nested RecyclerView... Как использовать: 1) Добавляем интерфейс к вашим моделям public class YourModel implements ViewModel { ... } 2) Создаем лейяут для итема RecyclerView3) Инициализируем адаптер mRecyclerViewAdapter = new RendererRecyclerViewAdapter(getContext()); 4) Добавляем для каждой модели рендерер mRecyclerViewAdapter.registerRenderer(new ViewBinder<>( R.layout.item_layout, //ID лейяута созданного в пункте 2 YourModel.class, //класс вашей модели (model, finder, payloads) -> finder .find(R.id.custom, (ViewProvider ) customView -> { ... }) .setBackground(R.id.image, model.getBackground()) .setText(R.id.text, model.getText()) .setOnClickListener(R.id.button, v -> { ... }) )); mRecyclerViewAdapter.registerRenderer(new ViewBinder<>( R.layout.other_item_layout, OtherYourModel.class, (model, finder, payloads) -> finder //... ));
Комментариев нет:
Отправить комментарий