优雅的展示RecyclerView数据集为空的状态

前言

RecyclerView 现在几乎是每一个 Android 项目都会用到的控件。大家都知道 RecyclerView 通过 Adapter 来将数据和界面进行绑定展示。但是在开发过程中,相信大家都会碰到这样一个需求,当 RecyclerView 绑定的数据集为空时,需要让用户知道当前展示的列表没有数据,否则界面就是一片空白,给用户的体验很不好。

常规实现方式

为了实现这一需求有很多种方法,比如在 RecyclerView 上覆盖一层布局,当数据集为空时显示该布局,否则就隐藏该布局。这种方法是一般思路,最容易想到。但是个人很不喜欢的一点就是繁琐,试想一下,你需要在每一个 RecyclerView 上都嵌套一个布局,同时当项目比较大时,多个地方都用到 RecyclerView,那么需要重复写很多遍,当然此处可以做封装界面,但是数据的逻辑交互也需要单独判断,不易于维护,并且造成相似代码的冗余。

期望

本人在想,有没有一种简单的方式,无需封装 ui, 我只关心 RecyclerView 数据集的变化,当数据集为空时自动显示为空的提示界面,同时又不希望造成多余的布局冗余,直接利用现成的 RecyclerView 展示提示界面。但是至于提示界面我又希望可以定制化,这样在不同的需求下可以展示不同的提示信息。所以我们需要实现以下几点功能:

  1. 直接利用 RecyclerView 展示提示信息
  2. 当数据为空的时候自动显示提示界面,有数据的时候显示正常界面
  3. 可灵活定制提示信息界面

实现

利用 RecyclerView 展示不同的布局,我们自然会想到利用 ViewHolder 去进行显示,那么就要用到 viewType.

首先我们需要先定义一种 viewType 为空类型(此处以空数据举例,当然你也可以定义一些其他类型,比如登录、无网络状态等等)。当 viewType 为空状态时,则展示空数据的界面,如果有数据则正常展示。

1
2
3
4
5
6
7
8
9
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case TYPE_EMPTY:
return new EmptyViewHolder(parent);
default:
return new DataViewHolder(parent);
}
}

接下来就是考虑如何根据如何设置 viewType 的值了,我们都知道可以根据 int getItemViewType(int position) 方法去设置不同的 viewType, 可是存在一个问题,当数据集为空时,正常情况下 item 个数为0,怎么去显示一个空界面呢。我想到采用曲线救国的方法,如下:

1
2
3
4
5
6
7
8
@Override
public final int getItemCount() {
return getCount() == 0 ? 1 : getCount();
}
private int getCount() {
return data == null ? 0 : data.size();
}

自行定义一个 getCount() 方法,这个方法用于指定正常数据的大小,当该方法返回为0时候,说明没有数据集合,那么在 Adapter 的getItemCount() 方法中返回1。

这样一来我们就可以重写 getItemViewType() 方法

1
2
3
4
5
6
7
@Override
public int getItemViewType(int position) {
if (getCount() == 0){
return TYPE_EMPTY;
}
return super.getItemViewType(position);
}

说到这里,其实已经基本实现了我们设定好的需求,下图是我写的 demo 效果图demo.gif

后记

  1. 由于当界面没有数据只显示空数据界面时,推荐将 EmptyViewHolder 的布局文件的宽和高都设置成 match_parent
  2. 由于本文只是阐述个人的一个思路,故不提供封装的 Adapter, 各位看官可根据自己的实际需求自行分装。
  3. 本文只提供了关于空数据的界面展示,但可以发散思维,显示数据加载错误时的状态、或者需要先登录时的状态等等,此处不再赘述
  4. 本文 demo 代码已上传,如需查阅,请自行前往
  5. 一家之言,欢迎交流,不喜勿喷!