Andorid上拉加载更多的几种实现方式
1.前言
Andriod中上拉加载更多的效果随处可见,因为一次性要展现的数据太多信息量太大的话,给用户的体验就很差(加载慢,界面卡顿、流量消耗大等),而加载更多可以控制每次加载条目的数量以达到快速加载,底部加载更多的方式就显得更人性化,今天就把用过的几种方式总结一下.
2.上拉加载更多的实现方式
- ListView控件;作为一种传统列表展现的方式,ListView控件的addHeaderView(...)、addFooterView(...)方法很方便的支持头布局、脚布局,参数就是打气筒打出来的布局.这个很常见,也算是一种屡试不爽的方式.
- RecyclerView控件;它是Android5.0以后推出的新控件,在v7包中,可以完美向下兼容,相比于ListView可定制性更大.并且RecyclerView本身不参与任何视图相关的问题,它不关心如何将子View放在合适的位置,也不关心如何分割这些子View,更不关心每个子View各自的外观。更进一步来说就是RecyclerView它只负责回收和重用的工作,这也是它名字的由来.
它并没有现成的下拉刷新和上拉加载的实现.下拉刷新可以配合SwipeRefreshView实现,这个较简单,来看下RecyclerView的加载更多实现方式.
思路:recyclerView.addOnScrollListener(...),通过监听recyclerview的滚动状态,判断是滚动状态且最后可见条目是最后一条时,加载更多.
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
} @Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
Log.d("==MainActivity==", "onScrolledStart");
super.onScrolled(recyclerView, dx, dy);
int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
int count = adapter.getItemCount();
if (lastVisibleItemPosition + 1 == count )
{
Log.d("==MainActivity==", "loading excute");
if (!isLoading) {
isLoading = true;
handler.postDelayed(new Runnable() {
@Override
public void run() {
isLoading = false;
//加载更多数据
addData();
}
}, 2000); }
} }
});public void addData() {
adapter.addData(originalData);
}
public class RecyclerViewAdapter extends RecyclerView.Adapter<ViewHolder> {
    private static final int TYPE_ITEM = 0;
    private static final int TYPE_FOOTER = 1;
    private Context context;
    private List<Map<String,Object>> datas;
    public RecyclerViewAdapter(Context context) {
        this.context = context;
        datas = new ArrayList();
    }
    public void addData(List data) {
        datas.addAll(data);
        this.notifyItemRangeChanged(0, datas.size());
    }
    public interface OnItemClickListener {
        void onItemClicked(View view, int position);
        void onItemLongClicked(View view, int position);
    }
    private OnItemClickListener onItemClickListener;
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }
    @Override
    public int getItemCount() {
        int aa = datas.size() == 0 ? 0 : datas.size() + 1;
        return aa;
    }
    @Override
    public int getItemViewType(int position) {
        if (position + 1 == getItemCount()) {
            return TYPE_FOOTER;
        } else {
            return TYPE_ITEM;
        }
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //加载每个列表项
        if (viewType == TYPE_ITEM) {
            View view = LayoutInflater.from(context).inflate(R.layout.item_base, parent, false);
            return new ItemViewHolder(view);
        }
        if (viewType == TYPE_FOOTER) {
            View view = LayoutInflater.from(context).inflate(R.layout.item_foot, parent, false);
            return new FootViewHolder(view);
        }
        return null;
    }
    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        //加载每个列表项的数据
        if (holder instanceof ItemViewHolder) {
            Map<String, Object> listItem = datas.get(position);
            ((ItemViewHolder) holder).name.setText((String)listItem.get("personName") + "  ------------" + String.valueOf(position));
            ((ItemViewHolder) holder).decs.setText((String)listItem.get("desc"));
            ((ItemViewHolder) holder).header.setImageResource((int)listItem.get("header"));
            if (onItemClickListener != null) {
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int position = holder.getLayoutPosition();
                        onItemClickListener.onItemClicked(holder.itemView, position);
                    }
                });
                holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        int position = holder.getLayoutPosition();
                        onItemClickListener.onItemLongClicked(holder.itemView, position);
                        return false;
                    }
                });
            }
        }
    }
    static class ItemViewHolder extends ViewHolder {
        TextView name;
        TextView decs;
        ImageView header;
        public ItemViewHolder(View view) {
            super(view);
            decs = (TextView)view.findViewById(R.id.desc);
            name = (TextView)view.findViewById(R.id.name);
            header = (ImageView)view.findViewById(R.id.header);
        }
    }
    static class FootViewHolder extends ViewHolder {
        public FootViewHolder(View view) {
            super(view);
        }
    }
}
值得注意的就是getItemCount()方法返回的是数据总条目数+1,getItemViewType(int position) 方法返回当前position对应的条目类型,既然要底部加载更多,那就是2种不同的类型;
而onCreateViewHolder(ViewGroup parent, int viewType) 肯定是返回对应的这两种ViewHolder;onBindViewHolder方法就是依据holder决定绑定对应怎样的视图.
3.对RecyclerView二次封装的开源框架;常用的有UltimateRecyclerView(解决RecyclerView下拉刷新,加载更多,增加头部,显示或隐藏工具栏等许多问题的知名开源框架)、
PullLoadMoreRecyclerView(属性最全,实现了RecyclerView下拉刷新和上拉加载更多以及RecyclerView线性、网格、瀑布流效果)、SwipeToLoadLayout支持多种基于RecyclerView的上拉加载和下拉刷新样式; 以PullLoadMoreRecyclerView为例子简单介绍其使用方式:
build.gradle添加依赖:
   dependencies {    compile 'com.wuxiaolong.pullloadmorerecyclerview:library:1.0.4'   }    mPullLoadMoreRecyclerView = (PullLoadMoreRecyclerView) view.findViewById(R.id.pullLoadMoreRecyclerView);    mPullLoadMoreRecyclerView.setLinearLayout();    mPullLoadMoreRecyclerView.setOnPullLoadMoreListener(new PullLoadMoreRecyclerView.PullLoadMoreListener() {            @Override            public void onRefresh() {//下拉刷新时调用            }            @Override            public void onLoadMore() {//上拉加载更多时调用                           }        })mPullLoadMoreRecyclerView.setPullLoadMoreCompleted();//加载结束时调用
此外还有很多个性化的接口方法暴露,很方便开发时使用.这里就不一一介绍了.具体可以去Github上搜索.
3.总结
按时间来说,我用得最多的是ListView,但是头布局越来越多后,position的转换显得很麻烦,而且recyclerview的缓存和回收机制更高效,recyclerview早就挡不住了,
listview和Gridview正在被recycleview替代,了解一些优秀的开源框架对开发事半功倍,但是我要强调的是这些框架的具体实现原理如果搞懂的话,可以形成自己的东西,有时间自己也能写出高效的框架来.后面也会深入理解.
Andorid上拉加载更多的几种实现方式的更多相关文章
- 原生js移动端touch事件实现上拉加载更多
		大家都知道jQuery里没有touch事件,所以在移动端使用原生js实现上拉加载效果还是很不错的,闲话不多说,代码如下: //获取要操作的元素 var objSection = document.ge ... 
- H5基于iScroll实现下拉刷新,上拉加载更多
		前言 前一段有个手机端的项目需要用到下拉刷新和上拉加载更多的效果,脑海里第一反映就是微博那种效果,刚开始的理解有些偏差,以为下拉也是追加数据,上拉也是追加数据,后请教同事后发现其实下拉只是刷新最新数据 ... 
- 常见开发需求之angular上拉加载更多
		需求 移动端使用angular实现上拉加载更多的条目,这个需求比较常见,网上的插件改动起来比较麻烦,不如自己写一个最适合,以前有同事写了一个,奈何bug太多,后来改分页了,我们产品说什么都让做,没 ... 
- ListView实现Item上下拖动交换位置  并且实现下拉刷新  上拉加载更多
		ListView实现Item上下拖动交换位置 并且实现下拉刷新 上拉加载更多 package com.example.ListViewDragItem; import android.app.Ac ... 
- ionic 上拉加载更多&瀑布流加载&滚动到底部加载更多 主意事项
		首先下拉刷新的代码是这样的,标红的地方为关键代码 <html> <head> <meta charset="utf-8"> <meta n ... 
- android ListView下拉刷新 上拉加载更多
		背景 最近在公司的项目中要使用到ListView的下拉刷新和上拉加载更多(貌似现在是个项目就有这个功能!哈哈),其实这个东西GitHub上很多,但是我感觉那些框架太大,而且我这个项目只用到了ListV ... 
- Android 上拉加载更多功能
		前几天看了github上面的例子,参照它的实现,自己又稍微改了一点,往项目里面增加了一个上拉加载更多功能.具体的实现如下: 首先要重写ListView: import android.content. ... 
- android ListView上拉加载更多 下拉刷新功能实现(采用pull-to-refresh)
		Android实现上拉加载更多功能以及下拉刷新功能, 采用了目前比较火的PullToRefresh,他是目前实现比较好的下拉刷新的类库. 目前他支持的控件有:ListView, ExpandableL ... 
- RecyclerView实例-实现可下拉刷新上拉加载更多并可切换线性流和瀑布流模式(1)
		摘要 最近项目有个列表页需要实现线性列表和瀑布流展示的切换,首先我想到的就是上 [RecyclerView],他本身已经很好的提供了三种布局方式,只是简单做个切换应该是很简单的事情,如果要用Recyc ... 
随机推荐
- mysql查看表结构,字段等命令
			mysql查看表结构命令,如下: desc 表名; show columns from 表名; describe 表名; show create table 表名; 
- CF #502
			#include<cstdio> #include<string> #include<cstdlib> #include<cmath> #include ... 
- upm配置文件
			组件配置说明 Ø 配置文件规范 Ø 组件分为公共组件和私有组件,分别在public段和private段,如下所示. <?xml version="1.0" encoding= ... 
- Python开发基础-Day8-装饰器扩展和迭代器
			wraps模块 让原函数保留原来的说明信息 import time import random from functools import wraps def auth(func): '''auth ... 
- CXF浅析
			CXF 框架支撑环境 CXF 框架是一种基于 Servlet 技术的 SOA 应用开发框架,要正常运行基于 CXF 应用框架开发的企业应用,除了 CXF 框架本身之外,还需要 JDK 和 Ser ... 
- RUP你知道多少?
			RUP 相信学UML的同学,对此都很耳熟,当然也眼熟,可是,对于RUP,你了解多少呢? 首先,什么是RUP? RUP是Rational UnifiedProcess,统一软件开发过程,是一个面向对象且 ... 
- 企鹅----sap+裂点
			企鹅 题目描述 在靠近南极的某处,一些企鹅站在许多漂浮的冰块上.由于企鹅是群居动物,所以它们想要聚集到一起,在同一个冰块上.企鹅们不想把自己的身体弄湿,所以它们在冰块之间跳跃,但是它们的跳跃距离,有一 ... 
- 用flask开发个人博客(26)—— 利用config.py配置文件动态的创建不同的Flask对象
			原文:https://blog.csdn.net/hyman_c/article/details/52877704 对配置进行封装的目的是根据不同的使用场景,给flask的app赋予不同的config ... 
- 通过win下的eclipse连接虚拟机中伪分布的hadoop进行调试
			VMware虚拟机配置Ubuntu桥接方式(Bridged)使虚拟机和宿主机能互相ping通, 通过win下的eclipse连接虚拟机中伪分布的hadoop进行调试 1.设置Bridged上网方式 V ... 
- Inno Setup自定义卸载文件名称的脚本
			Inno Setup 支持在同一个目录中安装多个应用程序,所以根据安装的先后次序自动将卸载程序文件命名为 unins000.exe,unins001.exe,unins002.exe 等等.这是 IN ... 
