Как реализовать множественные типы просмотра для RecycleView?

В настоящее время я работаю над пользовательскими типами многократного просмотра для RecycleView. Я нашел много решений для этой проблемы, но я поделюсь своим путем.

Разным является использование enum для определения ViewType.

См. мой ответ для более подробной информации. (Просто хочу поделиться).

Ответ 1

Вот как я настраиваю типы многозадачности для RecyclewView.

Сначала я покажу код, а затем поясню ниже.

@SuppressWarnings("unchecked")
public class BaseAdapter extends RecyclerView.Adapter<BaseAdapter.ViewHolder> {
    private final List<Wrapper<?>> items;

    public BaseAdapter() {
        this.items = new ArrayList<>();
    }

    @Override
    public int getItemViewType(int position) {
        return items.get(position).viewType;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return ViewType.values()[viewType].onCreateViewHolder(parent);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.onBind(items.get(position));
    }

    @Override
    public int getItemCount() {
        return items.size();
    }


    public void simulateAddItems() {
        items.add(new Wrapper<>(ViewType.USER.viewTYpe(), new User()));
        items.add(new Wrapper<>(ViewType.USER.viewTYpe(), new User()));
        items.add(new Wrapper<>(ViewType.USER.viewTYpe(), new User()));
        items.add(new Wrapper<>(ViewType.BOTTOM.viewTYpe(), new BottomData()));

        notifyDataSetChanged();
    }

    public enum ViewType {
        USER {
            @Override
            public ViewHolder onCreateViewHolder(ViewGroup parent) {
                return new UserViewHolder(itemView);
            }
        },
        BOTTOM {
            @Override
            public ViewHolder onCreateViewHolder(ViewGroup parent) {
                return new BottomViewHolder(itemView);
            }
        };

        public abstract ViewHolder onCreateViewHolder(ViewGroup parent);

        public int viewTYpe() {
            return ordinal();
        }
    }


    static class Wrapper<T> {
        final int viewType;
        final T data;

        public Wrapper(int viewType, T data) {
            this.viewType = viewType;
            this.data = data;
        }
    }

    public static class ViewHolder<T> extends RecyclerView.ViewHolder {
        private T item;

        public ViewHolder(View itemView) {
            super(itemView);
        }


        public void onBind(T item) {
        }
    }

    public static class UserViewHolder extends ViewHolder<User> {

        public UserViewHolder(View itemView) {
            super(itemView);
        }

        @Override
        public void onBind(User item) {
            super.onBind(item);
        }
    }

    public static class BottomViewHolder extends ViewHolder<BottomData> {

        public BottomViewHolder(View itemView) {
            super(itemView);
        }

        @Override
        public void onBind(BottomData item) {
            super.onBind(item);
        }
    }


    static class User {
        // user fields & method
    }

    static class BottomData {
        // bottom data fields & method
    }
}

Вы можете видеть, что адаптер имеет что-то особенное:

  • Данные адаптера являются обобщенными и простираются от класса Wrapper. Класс Wrapper просто POJO-класс содержит два поля viewType и item данных. viewType будет проходить через getItemViewType(int position), а item - данные для каждого держателя вида.

  • Общий ViewHolder с T является видом данных для владельца вида. Вы можете увидеть два пользовательских держателя вида UserViewHolder и BottomViewHolder, начиная с ViewHolder с этими данными. (Таким образом, в onBind каждого держателя вида будут указаны точные данные, которые они хотят использовать, → нет необходимости бросать. Потому что мы уже в литье).

  • В перечислении viewType содержится весь вид типа адаптера. Кроме того, в виде вида у нас есть метод ViewHolder onCreateViewHolder(ViewGroup parent), поэтому мы можем проще сделать viewHolder из viewType. Я думаю, что для наших глаз легче видеть Холдера относительно ViewType.

Кроме того, у нас есть метод viewType(), который просто возвращает ordinal() перечисления. В качестве ссылки в java docs этот метод не может использоваться. Но в этом случае я считаю, что это достаточно справедливо для использования (потому что оно уникально).

Итак, в методе onCreateViewHolder адаптера мы можем просто позвонить: return ViewType.values()[viewType].onCreateViewHolder(parent);

и в onBindViewHolder будем называть holder.onBind(items.get(position));.

Наконец, я сделал simulateAddItems для демонстрации того, как мы добавляем элемент в адаптер.

Вот некоторые впечатления при работе с настраиваемым типом вида для RecycleView. Надеюсь, это полезно и поможет другим людям.