android 下拉刷新使用

本文介绍了一种在安卓开发中实现列表分页加载的方法,通过自定义ListView组件并结合下拉刷新功能,有效地提升了用户体验及APP性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

***************************************

在经过几年的经验累积之后,我终于决定整理一下曾经遇到的各种问题,给各位走在android开发路上的朋友一点帮助,更多相关问题,请访问我的博客:http://blog.youkuaiyun.com/xiaoliluote  如果您对该问题有更多的解决方式,请留言,验证之后我会编辑博客

***************************************


我们会发现,有时我们的listview 需要加载很多的数据,如果数据量足够大的时候,就可能会让这个加载数据变得非常慢,即使是使用新线程来加载数据,也会等待较长的时间, 于是下拉刷新/ 上拉刷新的功能就出现了,每次可能只显示10条或者20条数据,然后当用户下拉/上拉  到最后一条/第一条 数据,就 再次加载10条/20条数据,这样可以大大提升APP的反应速度,非常赞! 


这里楼主以下拉刷新为例,给大家演示,上拉刷新的原理和下拉刷新的原理一致,大家可以举一反三,达到更好的学习效果


进入主题,下拉刷新是应用在listview中的,最简单的使用listview,我们使用系统的SimpleAdapter就可以了,xml 的界面呢,也只需要直接使用<ListView>即可, 但是由于我们需要监听用户的手势(下拉滚动),那么我们就需要自定义listview 的控件,

 这里楼主提示一点:对于有些可以重复利用的代码,我们要有意识的整理出来,尽量的提高代码的可重复调用性,不要将类似的代码都写一次,那样会使得代码臃肿,也不太好维护。 


这里楼主创建了一个类名为PaginationListView 的文件,代码如下:

public class PaginationListView extends ListView implements OnScrollListener{

 private View footerView; //定义下拉到底部时,给用户看什么东西,一般是一个图片+ 提示的文字
 int totalItemCount = 0;
 int lastVisibleItem = 0;
 boolean isLoading = false;
 
 public PaginationListView(Context context) {
   super(context);
   initView(context);
 }
 
 public PaginationListView(Context context, AttributeSet attrs) {
   super(context, attrs);
   initView(context);
   
 }

 public PaginationListView(Context context, AttributeSet attrs, int defStyle) {
   super(context, attrs, defStyle);
   initView(context);
 }


 private void initView(Context context){
   LayoutInflater mInflater = LayoutInflater.from(context);
   footerView = mInflater.inflate(R.layout.footer, null);
   footerView.setVisibility(View.GONE);  //数据初始时,下拉的提示是隐藏的
   
   this.setOnScrollListener(this); //监听滚动方法


   this.addFooterView(footerView);
 }


 @Override
 public void onScrollStateChanged(AbsListView view, int scrollState) {


   if(lastVisibleItem == totalItemCount && scrollState == SCROLL_STATE_IDLE){
     if(!isLoading){
       isLoading = true;


       footerView.setVisibility(View.VISIBLE);


       onLoadListener.onLoad();
     }
   }
 }


 @Override
 public void onScroll(AbsListView view, int firstVisibleItem,
     int visibleItemCount, int totalItemCount) {
   this.lastVisibleItem = firstVisibleItem + visibleItemCount;
   this.totalItemCount = totalItemCount;
 }
 
 private OnLoadListener onLoadListener;   //定义一个回调函数,用于返回到加载数据的类,去更新数据
 public void setOnLoadListener(OnLoadListener onLoadListener){
   this.onLoadListener = onLoadListener;
 }
 
 public interface OnLoadListener{
   void onLoad();
 }
 

//当数据加载完毕之后,那么就要再次隐藏提示的底部文件
 public void loadComplete(){
   footerView.setVisibility(View.GONE);
   isLoading = false;
   this.invalidate();
 }
}


这里提供一下我的底部提示文件 footer.xml 各位可以根据自己的需要自行补脑,做出更好看的效果

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/footer_ll"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:gravity="center"
  
  android:orientation="horizontal" >


  <ProgressBar
    android:id="@+id/progress"
    style="?android:attr/progressBarStyleSmall"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="30dp"
    android:layout_marginTop="30dp" />


  <MY_extend.my_textview
    android:id="@+id/tv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:text="pleast wait while load data..."
    android:textColor="#FF0000" />


</LinearLayout>


然后呢,我们的界面,就不要再用 <ListView>  啦,改用我们上面的这个

<PaginationListView
        android:id="@+id/dyn_browse_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="3dp"
        android:paddingRight="3dp" >
    </PaginationListView>


接下来回到我们的activity 中,首先,这个 activity 需要实现 OnLoadListener监听

public class Act_Contact_Browse extends Activity implements OnLoadListener{}

会实现一个方法

@Override
public void onLoad() {}

然后获取到界面上的ListView 

PaginationListView    contact_list = (PaginationListView) findViewById(R.id.dyn_browse_list);

设置监听

 contact_list.setOnLoadListener(this);


接下来就可以设定值到我们的 适配器(也许你使用的就是最简单的SimpleAdapter),这里楼主是自己定义的适配器

不过这个无关紧要,都一样,然后呢,我们需要设定全局变量

public int paginationCode = 10;  //设定每页显示多少条数据

public ArrayList<HashMap<String, Object>> paginationList; //显示到界面上的数据

public ArrayList<HashMap<String, Object>> _rawData; // 原始的数据, 因为原始的数据可能有100条,但是每次只取10条到界面,所以用了两个参数


然后楼主写了一个方法来加载这些数据,这个方法呢,也许有点复杂,你看不明白,不过没关系,拿过来直接用就可以了,有时间的就可以仔细看一下逻辑。 因为我们要判断几个条件,比如:

1.如果总数据一共不足10条,那么就不会出现滚动的监听,底部的提示也不会出现

2.如果10< 数据 <20 ,那么第一次能滚动,第二次就不会再出现那滚动的提示了 


private void LoadPaginationData() {
if (paginationCode == 10) {
if (_rawData.size() > 10) {
for (int i = 0; i < paginationCode; i++) {
paginationList.add(_rawData.get(i));
}
} else {


for (int i = 0; i < _rawData.size(); i++) {
paginationList.add(_rawData.get(i));
}
}
if (paginationList.size() != 0) {
if (_rawData.size() > paginationCode + 10)
paginationCode += 10;
else if (_rawData.size() > 10)
paginationCode = paginationCode + _rawData.size() - paginationCode;
}


} else {


if (_rawData.size() > paginationCode + 10) {
for (int i = paginationCode; i < paginationCode + 10; i++) {
paginationList.add(_rawData.get(i));
}
} else {
if (_rawData.size() - paginationCode > 0) {
for (int i = paginationList.size(); i < paginationCode; i++) {
paginationList.add(_rawData.get(i));
}
} else {
for (int i = paginationList.size(); i < _rawData.size(); i++) {
paginationList.add(_rawData.get(i));
}
}
}


if (paginationList.size() != 0) {
if (_rawData.size() > paginationCode + 10)
paginationCode += 10;
else if (_rawData.size() - paginationList.size() > 0)
paginationCode = paginationCode + _rawData.size() - paginationCode;
}


}


}



接下来我们就要去我们的onload 方法里面写东西了, 当用户滚动到最后一条,我们最早写的那个 自定义的listview 类,会调用我们的回调函数(onload),我们在这个方法里面去更新数据

@Override
public void onLoad() {
if (_rawData.size() > paginationList.size()) {
new Handler().postDelayed(new Runnable() {


@Override
public void run() {
LoadPaginationData();
adr_contact.updateView(paginationList); //这个方法是我的自定义的适配器里面的方法,我传递了一个参数过去

//这个参数就是最新的数据
adr_contact.notifyDataSetChanged(); //然后调用这个方法,适配器就会重新调用一次 getView方法,然后把我的最新的数据

//加载进去
contact_list.loadComplete(); //加载完成了之后,调用我们自定义的listview里面的这个方法,隐藏掉底部的提示
}
}, 1);
} else {
contact_list.loadComplete();
}

}



自定义适配器的所有代码我就不贴了,贴一下部分代码

public void updateView(ArrayList<HashMap<String, Object>> datas) {
_rawData = datas; //传递最新的数据过来
}


然后getView 方法里面,所有的数据,都是从 _rawData 里面取出来的


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值