android架构组件之paging如何优雅实现加载提示

在使用paging的过程中,使用起来是很方便,但也发现一些问题,比如往下滑的时候,没有加载的提示(数据正在加载中),这个时候就需要我们去处理了,数据加载可能是成功了,可能是失败了,也可能是全部加载完成了,加载过程中还有加载的结果都是需要一个友好的提示的,我们看到好多APP应用都是在item底部会有一个友好的提示,所有这边文章就是来实现如何在底部添加一个友好提示的item,数据加载成功后会自动消失。

加载数据的几种状态

加载数据可以分为加载过程中,加载成功,加载失败,数据全部加载完成,如果还有其他状态可自行添加,根据这些状态就可以定义一个枚举类来描述这几种情况:

public enum RequestDataState {
    //加载过程中
    LOADING, 
    //加载成功
    SUCCESS, 
    //加载失败
    FAIL, 
    //全部加载完成
    COMPLETE
}

数据加载

对于paging来说,数据加载的功能全部交给了DataSource,DataSource有三个子类,我们可以根据不同的需求去实现对应的子类,这里以PageKeyedDataSource为例进行说明,其他的类似,为了处理加载数据的几种状态并且通用性强,可以将这个功能抽象出来,之后要同步加载状态的全部去实现这个类就可以了,这个还比较简单,类的定义如下:

public abstract class PageKeyedLoadDataSource<K, V> extends PageKeyedDataSource<K, V> {

    //存储请求数据后的状态
    private MutableLiveData<RequestDataState> netDataStateLiveData = new MutableLiveData<>();

    public MutableLiveData<RequestDataState> getNetDataStateLiveData() {
        return netDataStateLiveData;
    }

    @Override
    public void loadAfter(@NonNull LoadParams<K> params, @NonNull LoadCallback<K, V> callback) {
        updateNetState(RequestDataState.LOADING);
        RequestDataState requestDataState = loadAfter1(params, callback);
        //加载数据失败后,为下次重试加载提供参数
        if (requestDataState == RequestDataState.FAIL) {
            this.params = params;
            this.callback = callback;
        }
        updateNetState(requestDataState);
    }

    private LoadParams<K> params;
    private LoadCallback<K, V> callback;
    //数据加载失败后可以尝试重新进行加载
    public void retryAfter(){
        loadAfter(params,callback);
    }

    private void updateNetState(RequestDataState state) {
        netDataStateLiveData.postValue(state);
    }

    /**
     * @param params
     * @param callback
     * @return true加载数据成功 false加载数据失败
     */
    public abstract RequestDataState loadAfter1(@NonNull LoadParams<K> params, @NonNull LoadCallback<K,V> callback);
}

这里提供了一个抽象方法loadAfter1(),返回请求数据的状态就好,这样封装好后,其他使用都是一样的,所以这里还是比较方便的,接下来才是重点。

数据加载状态显示

对于数据显示,自然想到的就是PagedListAdapter了,这里就是通过它来显示加载状态的,问题又来了,如何才能解耦呢?就是再次封装下PagedListAdapter,处理对请求数据状态的显示,如下:

public abstract class PagedListLoadAdapter<T, VH extends RecyclerView.ViewHolder> extends PagedListAdapter<T, RecyclerView.ViewHolder> {
    //定义加载数据显示的几种状态
    private static final int TYPE_LOAD_LOADING = 1002;
    private static final int TYPE_LOAD_ALL_COMPLETE = 1003;
    private static final int TYPE_LOAD_FAIL = 1004;
    //当前请求数据的状态
    private RequestDataState state;
    private LifecycleOwner owner;

    PagedListLoadAdapter(@NonNull DiffUtil.ItemCallback diffCallback, LifecycleOwner owner) {
        super(diffCallback);
        this.owner = owner;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) {
        //这里加载过程中、加载失败、加载全部完成使用的是同一个布局,可根据需要自行定义
        if (type == TYPE_LOAD_LOADING || type == TYPE_LOAD_ALL_COMPLETE || type == TYPE_LOAD_FAIL) {
            View inflate = View.inflate(viewGroup.getContext(), R.layout.item_load_more, null);
            return new LoadingViewHolder(inflate);
        }
        return onCreateViewHolder1(viewGroup, type);
    }

    public abstract VH onCreateViewHolder1(@NonNull ViewGroup viewGroup, int type);

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
        //根据加载状态对item的提示的处理
        if (getItemViewType(position) == TYPE_LOAD_LOADING) {
            ((LoadingViewHolder) viewHolder).bindTo("正在加载数据,请稍候...");
            return;
        }
        if (getItemViewType(position) == TYPE_LOAD_ALL_COMPLETE) {
            ((LoadingViewHolder) viewHolder).bindTo("所有数据已全部加载完成");
            return;
        }
        if (getItemViewType(position) == TYPE_LOAD_FAIL) {
            ((LoadingViewHolder) viewHolder).bindTo("加载数据失败");
            return;
        }
        onBindViewHolder1(viewHolder, position);
    }

    public abstract void onBindViewHolder1(@NonNull RecyclerView.ViewHolder viewHolder, int position);

    @Override
    public int getItemCount() {
        if (state == RequestDataState.LOADING || state == RequestDataState.COMPLETE || state == RequestDataState.FAIL) {
            return super.getItemCount() + 1;
        }
        return super.getItemCount();
    }

    @Override
    public int getItemViewType(int position) {
        if (position == getItemCount() - 1 && (state == RequestDataState.LOADING))
            return TYPE_LOAD_LOADING;
        if (position == getItemCount() - 1 && (state == RequestDataState.FAIL))
            return TYPE_LOAD_FAIL;
        if (position == getItemCount() - 1 && (state == RequestDataState.COMPLETE)) {
            View view = new TextView((Activity) owner);
            //3秒后不显示加载完成的提示
            view.postDelayed(() -> {
                PagedListLoadAdapter.this.state = RequestDataState.SUCCESS;
                notifyItemChanged(getItemCount());
            }, 3000);
            return TYPE_LOAD_ALL_COMPLETE;
        }
        return super.getItemViewType(position);
    }

    @Override
    public void onCurrentListChanged(@Nullable PagedList<T> currentList) {
        super.onCurrentListChanged(currentList);
        PagedList<T> pagedList = getCurrentList();
        if (null == pagedList) {
            return;
        }
        DataSource<?, T> dataSource = pagedList.getDataSource();
        if (dataSource instanceof PageKeyedLoadDataSource) {
            MutableLiveData<RequestDataState> netDataStateLiveData = ((PageKeyedLoadDataSource) dataSource).getNetDataStateLiveData();
            //对加载数据状态进行监听
            netDataStateLiveData.observe(owner, this::setNetState);
        }
    }

    public void setNetState(RequestDataState state) {
        this.state = state;
        notifyItemChanged(getItemCount());
    }

    private class LoadingViewHolder extends RecyclerView.ViewHolder {
        private TextView loadView;

        public LoadingViewHolder(@NonNull View itemView) {
            super(itemView);
            loadView = itemView.findViewById(R.id.load_msg);
        }

        public void bindTo(String s) {
            loadView.setText(s);
        }
    }
}

到这就算是完成了,其他所有的操作所有的和正常使用paging是一样的,只是继承的类换成是上面的PageKeyedLoadDataSource和PagedListLoadAdapter,这里需要注意PagedListLoadAdapter中定义的加载布局需要我们去定义,这样做完后,网络加载数据的提示就会自动完成。如果想要实现下拉刷新,可以使用android原生的SwipeRefreshLayout,同时需要替换掉PagedList,也就是重新在创建一个LivePagedListBuilder就ok了。

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Paging3 是一个用于在 Android 应用中实现分页加载数据的开源库。它是 Google 官方发布的最新版本的 Paging 库,相较于以往的版本,Paging3 在实现简单、功能强大和性能优化方面有了很大的改进。 首先,Android Paging3 提供了强大的数据加载和显示机制。它通过将数据分割成固定大小的数据块 (page),并在需要时按需加载和展示数据实现了无限滚动加载的效果。相较于传统的 RecyclerView 分页加载Paging3 更加灵活,可以自动处理数据加载和卸载,无需手动实现判断是否到底部、加载更多等繁琐逻辑。同时,Paging3 还支持局部刷新、数据源无缝替换等操作,让数据加载和显示更加简单和高效。 其次,Paging3 在性能方面进行了优化。它使用了异步数据加载和显示机制,可以在后台线程上进行数据加载,不会阻塞主线程。同时,Paging3 采用了数据加载和缓存策略,可以将下一页的数据提前加载到内存中,从而提高用户体验和应用的响应速度。并且,Paging3 还支持数据的持久化存储,可以将加载数据缓存到本地数据库或文件中,避免了重复加载数据的开销。 最后,Paging3 还提供了丰富的扩展功能和灵活的定制选项。开发者可以自定义数据加载策略、数据源类型、数据显示方式等,以满足不同的业务需求。同时,Paging3 还提供了相关的辅助类和工具方法,帮助开发者更加便捷地实现数据的分页加载和显示。 总结来说,Android Paging3 是一个功能强大、性能优越的分页加载库,可以帮助开发者轻松实现数据的分页加载和显示,提高应用的用户体验和性能表现。无论是处理大量数据的列表页,还是实现无限滚动加载的功能,Paging3 都是一个值得推荐的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值