如何为RecycleView实现多视图类型?

时间:2017-11-12 04:21:31

标签: android android-recyclerview recycler-adapter

目前,我正在为RecycleView开发自定义多视图类型。 我找到了很多这个问题的解决方案,但我会分享我的方式。

不同的是使用enum来定义ViewType。

有关详细信息,请参阅我的回答。 (只是想分享)。

1 个答案:

答案 0 :(得分:1)

<强>更新

我建议您阅读这篇文章:Writing Better Adapter

以下是我为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
    }
}

你可以看到适配器有一些特别的东西:

  1. 适配器的数据是通用的&amp;从Wrapper课程延伸。 Wrapper类只是POJO类包含两个字段viewType&amp; item数据。 viewType将通过getItemViewType(int position)传递,item是每个视图持有者的数据。

  2. 带有ViewHolder的通用T是视图持有者的一种数据。您可以使用此数据查看两个自定义视图持有者UserViewHolderBottomViewHolderViewHolder扩展而来。 (因此,在每个视图持有者的onBind中都会有他们想要使用的确切数据 - &gt;无需强制转换。因为我们已经投了广告。

  3. 枚举ViewType包含所有视图类型的适配器。另外,在视图类型中,我们有方法ViewHolder onCreateViewHolder(ViewGroup parent),因此我们可以更轻松地从ViewType创建viewHolder。我认为我们的眼睛更容易看到相对于ViewType的Holder。

  4. 另外,我们有方法viewType()它只返回枚举的ordinal()。 作为java docs中的参考,该方法可能无法使用。但在这种情况下,我认为使用它是公平的(因为它是独一无二的)。

    所以在Adapter的onCreateViewHolder方法中我们可以简单地调用: return ViewType.values()[viewType].onCreateViewHolder(parent);

    onBindViewHolder我们会致电holder.onBind(items.get(position));

    最后,我做了simulateAddItems演示了如何将项目添加到适配器。

    以下是使用RecycleView的自定义视图类型时的一些经验。我希望它有用&amp;帮助其他人。