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

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