У меня есть активность. В Activity находится ViewPager с вкладками, каждая вкладка содержит фрагмент. У самих фрагментов есть RecyclerView каждый. Мне нужно передать изменения из адаптера RecyclerView в действие.Коммуникация между компонентами в Android
В настоящее время я использую шаблон слушателя и общаюсь с использованием интерфейса между каждым из компонентов. Т.е. у меня есть интерфейс между адаптером RecyclerView и фрагментом, удерживающим его. Затем интерфейс из фрагмента в FragmentStatePagerAdapter ViewPager, который создает все фрагменты. И еще 1 интерфейс между адаптером ViewPager и Activity, в котором находится ViewPager. Я чувствую, что слишком много интерфейсов для всех компонентов из-за того, как они структурированы.
В настоящее время я не сталкиваюсь с проблемами как таковыми, но я думаю, что шаблон слушателя действует как анти-шаблон из-за всех вложенных компонентов. Вместо создания независимых компонентов, я думаю, что иерархия затруднит внесение изменений кода в будущем.
Я делаю это правильно или есть лучший способ сделать это? Является ли это случаем, когда я должен использовать шину событий или шаблон наблюдателя (если да, то можете ли вы указать мне некоторые примеры, когда кто-то преодолел подобные проблемы, используя его)?
ПРИМЕЧАНИЕ. Если это имеет значение, мне нужно, чтобы он поддерживал глобальный объект в активности, что-то вроде корзины покупок, где я могу добавлять или удалять элементы, и эти элементы присутствуют в адаптере RecyclerView, откуда я могу добавить его в а также увеличивать или уменьшать счетчик для определенного элемента. ViewPager и вкладки помогают разделять эти элементы в разных категориях.
Редактировать 1: Некоторый код пытается @ подход LucaNicoletti - Я пропустил один уровень, который является уровнем с помощью параметра FragmentStatePagerAdapter ViewPager. Думаю, это не имеет значения и лишено какого-либо другого кода, чтобы он был маленьким.
MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener, FoodAdapter.OnFoodItemCountChangeListener {
@Override
public void onFoodItemDecreased(FoodItemModel foodItemModel, int count) {
Log.d("Test", "Dec");
}
@Override
public void onFoodItemIncreased(FoodItemModel foodItemModel, int count) {
Log.d("Test", "Inc");
}
// Other methods here
}
Фрагмент хостинг адаптер:
public class FoodCategoryListFragment extends Fragment implements FoodAdapter.OnFoodItemCountChangeListener {
// Other boring variables like recyclerview and layout managers
FoodAdapter foodAdapter;
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Other boring intializations for recyclerview and stuff
// I set the click listener here directly on the adapter instance
// I don't have this adapter instance in my activity
foodAdapter.setOnFoodItemClickListener(this);
rvFoodList.setAdapter(foodAdapter);
}
}
Класс адаптера на самом низком уровне:
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.FoodViewHolder> {
private OnFoodItemCountChangeListener onFoodItemCountChangeListener;
private List<FoodItemModel> foodItems;
// The interface
public interface OnFoodItemCountChangeListener {
void onFoodItemIncreased(FoodItemModel foodItemModel, int count);
void onFoodItemDecreased(FoodItemModel foodItemModel, int count);
}
// This is called from the fragment since I don't have the adapter instance
// in my activty
public void setOnFoodItemClickListener(OnFoodItemCountChangeListener onFoodItemCountChangeListener) {
this.onFoodItemCountChangeListener = onFoodItemCountChangeListener;
}
// Other boring adapter stuff here
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bMinus:
onFoodItemCountChangeListener.onFoodItemDecreased(foodItems.get(getAdapterPosition()),
Integer.parseInt(etCounter.getText().toString()));
}
break;
case R.id.bPlus:
onFoodItemCountChangeListener.onFoodItemIncreased(foodItems.get(getAdapterPosition()),
Integer.parseInt(etCounter.getText().toString()));
}
break;
}
}
}
Если слушатели в середине просто направить действия на более высокий уровень, удалить интерфейс к этому уровню, и использовать только выше один –
то, что вы должны/могли бы сделать это, чтобы иметь глобальный репозиторий данных, который держит корзины покупок и слушателей, связанных с изменениями в нем. Как и singleton, например 'ShoppingCart.getInstance(). AddListener (this);' и 'ShoppingCart.getInstance(). AddItem (новый элемент (id));' – Budius
@LucaNicoletti Но для того, чтобы установить слушателя, мне нужно иметь экземпляр самого низкого уровня на самом высоком уровне, чтобы установить его. Я сохранил указанные экземпляры на среднем уровне. Как и моя активность, отслеживаются следы ViewPager, и это, в свою очередь, отслеживает фрагменты с адаптером. У Activity нет экземпляра адаптера для установки на него слушателя. Прошу прощения, если это звучит неправильно в соответствии с шаблоном слушателя. –