Я использовал следующий подход.Обратите внимание, что ваш «Элемент» может быть вашей моделью представления, если вам нравится, к которому у вас есть доступ внутри привязанного макета для каждого элемента.И оттуда вы можете вызывать любой метод, который вы хотите внутри vm, или установить LiveData или что угодно, чтобы сообщить представлению отображать тост.Для этой цели я рекомендую использовать SingleLiveEvent .
Сначала я создал BaseAdapter.
public class BaseAdapter<T> extends ListAdapter<T, SingleItemViewHolder<T>> {
private final int variableId;
protected BaseAdapter(@NonNull DiffUtil.ItemCallback<T> diffCallback, int variableId) {
super(diffCallback);
this.variableId = variableId;
}
@NonNull
@Override
public SingleItemViewHolder<T> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ViewDataBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()), viewType, parent, false);
return new SingleItemViewHolder<>(binding, variableId);
}
@Override
public void onBindViewHolder(@NonNull SingleItemViewHolder<T> holder, int position) {
holder.bind(getItem(position));
}
}
Этот адаптер использует следующий SingleItemViewHolder.
public final class SingleItemViewHolder<T> extends RecyclerView.ViewHolder {
private final ViewDataBinding binding;
private final int variableId;
/**
* Constructor
*
* @param binding the binding to use
* @param variableId variable to set on the binding
*/
public SingleItemViewHolder(ViewDataBinding binding, int variableId) {
super(binding.getRoot());
this.binding = Objects.requireNonNull(binding);
this.variableId = variableId;
}
/**
* Sets the data binding variable to the provided item
* and calls {@link ViewDataBinding#executePendingBindings()}.
*
* @param item item to bind
* @throws NullPointerException if item is null ({@code item == null})
*/
public void bind(@NonNull T item) {
Objects.requireNonNull(item);
binding.setVariable(variableId, item);
binding.executePendingBindings();
}
}
Затем вы используете его, создав подкласс BaseAdapter и предоставив свой собственный DiffCallback и макет, подобный этому.
public final class ModelAdapter extends BaseAdapter<Model> {
public ModelAdapter() {
super(new DiffCallback(), BR.item);
}
@Override
public int getItemViewType(int position) {
return R.layout.item_model;
}
private static final class DiffCallback extends DiffUtil.ItemCallback<Model> {
@Override
public boolean areItemsTheSame(@NonNull Model oldItem, @NonNull Model newItem) {
return oldItem.id.equals(newItem.id);
}
@Override
public boolean areContentsTheSame(@NonNull Model oldItem, @NonNull Model newItem) {
return oldItem.equals(newItem);
}
}
}
Где Model - это простой объектный класс Java с некоторыми полями (не включены)для краткости).
Тогда раскладка, которая показывает фактическую модель и допускает привязку данных.
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="item"
type="com.example.models.Model" />
</data>
....
Затем вы можете просто использовать этот элемент внутри раскладки.
Пример использования бонуса
Затем создайте его экземпляр так, как вы хотите.Моя рекомендация, как я это сделал, состояла в том, чтобы создать экземпляр в представлении (фрагмент) присоединить его, используя привязку данных.
<data>
<variable
name="adapter"
type="com.example.ModelAdapter" />
</data>
....
<androidx.recyclerview.widget.RecyclerView
recycler_view_base_adapter_items="@{vm.models}"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adapter="@{adapter}"
android:orientation="vertical"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
С помощью следующего @ BindingAdapter.
@BindingAdapter(value = {"recycler_view_base_adapter_items"})
public static <T> void setRecyclerViewBaseAdapterItems(RecyclerView view,
@Nullable final List<T> items) {
final RecyclerView.Adapter viewAdapter = view.getAdapter();
if (viewAdapter == null || items == null) {
Timber.w("recycler_view_base_adapter_items did nothing.");
return;
}
try {
@SuppressWarnings("unchecked") final BaseAdapter<T> adapter = (BaseAdapter<T>) viewAdapter;
adapter.submitList(items);
} catch (ClassCastException e) {
Timber.e(e);
}
}