RecyclerView#Adapter支持无数据布局、错误布局和列表尾部的”没有更多了“布局

RecyclerView#Adapter支持无数据布局、错误布局和列表尾部的”没有更多了“布局

实际开发中,UI小姐姐都会提供通用的无数据页面错误提示页面

针对常见的支持下拉刷新和上拉加载更多的列表页面,将他们的通用逻辑抽取出来,这样我们在开发过程中就只需要关注具体的业务逻辑了,无需每次通过cv来完善无数据页面错误提示页面的逻辑了。

业务场景梳理

不支持分页

列表页根据业务场景中的是否需要分页来进行区分,不支持分页的逻辑简单。具体如下图所示:

不支持分页

不分页的列表页,请求数据后就三种结果:有数据无数据错误(当前页面无数据的前提下)

当然了 不支持分页的页面也就不需要支持上拉加载更多

支持分页

支持分页的话情况稍微复杂一点,具体业务逻辑看下图:

在这里插入图片描述

请求失败的逻辑跟不分页的场景一致。

请求成功后,需要判断是否需要清除原有数据(第一页需要清除,表示下拉刷新过);需要根据当前页码(pageNo)每页数据容量(pageSize),判断是否还有更多数据需要加载,如果没有更多数据了,则在列表底部显示没有更多布局。

实现思路

通过上面的梳理,可以看出实现的核心在于让RecyclerView.Adapter默认支持空数据页面错误数据页面没有更多布局

这个需求我们可以通过RecyclerView.Adapter.getItemCountRecyclerView.Adapter.getItemViewType来实现,通过唯一的type值来进行区分。

另外,我们还需要支持扩展,我们自己也可以添加多种类型的item,需要预留入口。

demo地址

FuncRecyclerView

如何使用

1、添加布局FuncRecyclerView

这里我们给FuncRecyclerView设置的宽高都是固定的。

<com.scwang.smart.refresh.layout.SmartRefreshLayout
    android:id="@+id/refreshLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.tinytongtong.funcrecyclerview.recyclerview.FuncRecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</com.scwang.smart.refresh.layout.SmartRefreshLayout>
2、创建数据model、viewholder和自定义的CommonFuncItem

我们自己的Item对应的数据model,需要实现FuncBaseBean接口,实现它的getViewType方法,该方法的返回值大于0,且在当前FuncRecyclerView实例中唯一即可。具体代码如下:

public class TestFuncBean implements FuncBaseBean {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int getViewType() {
        return 4;
    }
}

接着创建ViewHolder,继承CommonFuncViewHolder,具体代码如下:

static class NormalViewHolder extends CommonFuncViewHolder {
    public TextView tvName;

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

    public NormalViewHolder(View itemView, FuncBaseBean funcBaseBean) {
        super(itemView, funcBaseBean);
        tvName = itemView.findViewById(R.id.tv);
    }
}

使用创建好的Model和ViewHolder,创建自定义的CommonFuncItem,代码如下:

public class TestCommonFuncItem<V extends FuncBaseBean> extends CommonFuncItem<V> {
    public TestCommonFuncItem(V v) {
        super(v);
    }

    @Override
    public CommonFuncViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
        return new TestCommonFuncItem.NormalViewHolder(v, t);
    }

    @Override
    public void onBindViewHolder(final CommonFuncViewHolder vh, FuncBaseBean funcBaseBean, final int position) {
        final TestCommonFuncItem.NormalViewHolder holder = (NormalViewHolder) vh;
        TestFuncBean rib = (TestFuncBean) funcBaseBean;
        holder.tvName.setText(rib.getName());
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(holder.itemView.getContext(), String.format("点击了第%d条数据", position), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

可以看出,onCreateViewHolderonBindViewHolder方法跟RecyclerView.Adapter中的使用方法一样,唯一的区别是,onBindViewHolder方法中可以拿到对应的数据FuncBaseBean,不需要我们根据position再去获取一次。

3、代码添加viewholder

接下来就是使用了,具体代码如下:

初始化添加type:

TestFuncBean testFuncBean = new TestFuncBean();
recyclerView.addCommonFuncItem(new TestCommonFuncItem(testFuncBean));
4、设置数据

网络请求成功和失败的情况:

public void onSuccess(List<FuncBaseBean> list) {
    refreshLayout.finishLoadMore();
    refreshLayout.finishRefresh();
    PageListHelper.updateSinglePageList(recyclerView, list);
}

public void onFailure(Throwable e) {
    refreshLayout.finishLoadMore();
    refreshLayout.finishRefresh();
    Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
    PageListHelper.showError(recyclerView,e);
}
/**
 * 不分页的页面,更新数据
 *
 * @param recyclerView
 * @param list
 */
public static void updateSinglePageList(FuncRecyclerView recyclerView, List<FuncBaseBean> list) {
    if (list == null || list.isEmpty()) {
        recyclerView.showEmpty();
    } else {
        recyclerView.setList(list);
    }
}

public static void showError(FuncRecyclerView recyclerView, Throwable e) {
    if (recyclerView.getListSize() == 0) {
        recyclerView.showError();
    }
}

不分页的demo请看SimplePageListActivity,支持分页的demo请看MultiPageListActivity

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章