Правильный способ обращения с предметом Click Recycler View
У меня есть 5 строк для отображения в RecyclerView. Когда пользователь нажимает на один из элементов, открывается другое действие. Каждый предмет имеет различную активность. Я обработал событие нажатия, как показано ниже.
switch (getAdapterPosition()) {
case 1:
ActivityUtil.startActivity(itemView.getContext(), BlablaActivity.class);
break;
//other cases
}
Работает правильно. Но что, если новый элемент будет добавлен в список в будущем? Для каждого отдельного предмета я должен добавить новый кейс для коммутатора. Это не правильное решение в соответствии с Открытым Закрытым Принципом. Как мне справиться с этим? Любые предложения будут великолепны...
3 ответа
В идеале вы бы добавили Class<? extends Activity>
поле для класса, который представляет ваши элементы RecyclerView. Тогда вы можете просто получить доступ к этому полю в вашем прослушивателе кликов (этот код будет внутри onCreateViewHolder()
):
holder.itemView.setOnClickListener(v -> {
int position = holder.getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
Class<? extends Activity> activityClass = items.get(position).getActivityClass();
ActivityUtil.startActivity(v.getContext(), activityClass);
}
});
Таким образом, каждый элемент отвечает за знание того, куда идти при нажатии. Вы можете добавлять новые элементы в свой список, даже не трогая код адаптера.
Сначала сохраните действие, на которое ссылаются элементы, в вашей БД, а затем добавьте его в модель типизированного списка, если это так
yourlist.java
....
private String BLABLA;
private String BLABLA1;
private String ActivityName;
....
Затем в вашем адаптере OnBindViewholder OnClick сделать что-то вроде этого
@Override
public void onClick(View v) {
activityString = singleItem.getActivityName();
Intent intent= new Intent(context, Class.forName(activityString));
context.startActivity(intent);
}
});
Это может быть легко обработано, если вы строго заставляете адаптер RecyclerView работать только как представление, то есть отображать только данные вместе с представлением. Вся логическая ответственность за принятие решения должна быть делегирована обратно родительскому действию или фрагменту. Это может быть достигнуто с помощью Callback/Listener.
Всякий раз, когда есть событие click в элементе RecyclerView, сообщите родительскому действию или фрагменту, чтобы обработать его.
Вам нужно изменить свой адаптер на что-то вроде этого:
public class YourAdapter extends RecyclerView.Adapter<YourAdapter.ViewHolder> {
// Local variable for listener
private OnItemClickListener listener;
// Listener interface
public interface OnItemClickListener {
void onItemClick(View itemView, int position);
}
// set the listener on parent activity or fragment
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
....
public ViewHolder(final View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) return;
// tell the parent to handle the item.
listener.onItemClick(itemView, position);
}
});
}
}
}
Затем вы можете использовать следующее для обработки клика:
// assuming adapter is your adapter
adapter.setOnItemClickListener(new ContactsAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
handleItemClickByPosition(position);
}
});
...
private void handleItemClickByPosition(int position) {
switch (getAdapterPosition()) {
case 1:
ActivityUtil.startActivity(itemView.getContext(), BlablaActivity.class);
break;
//other cases
}
}
Следовательно, вам не нужно менять адаптер каждый раз, когда в вашем адаптере появляется новый элемент.