我们都知道网络取数据是耗时操作,如果我们一次性请求所有数据,假如数据量不多那还可以接受,但是如果数据量特别多,那么带来的后果就是用户的愤怒(用户是很没有耐心的),所以这时候我们就需要动态的加载数据,分批加载我们所需的数据,提升用户体验,先上图。

         

一般如果一个Activity集成越多的功能,代码量也会随之增多,看起来让人烦,我们可以考虑自定义控件将一些操作集成进去。

自定义ListView

 1 package com.example.listviewdynamicloading;
 2 
 3 import android.content.Context;
 4 import android.util.AttributeSet;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.widget.AbsListView;
 8 import android.widget.AbsListView.OnScrollListener;
 9 import android.widget.ListView;
10 
11 public class ZdyListView extends ListView implements OnScrollListener {
12     private int totalItemCount;// 总数量;
13     private int lastVisibleItem;// 最后一个可见的item;
14     private boolean isLoading;
15     private View footer;
16     private LayoutInflater inflater;
17     public RefleshDatas refleshDatas;
18 
19     public ZdyListView(Context context) {
20         super(context);
21         initView(context);
22     }
23 
24     public ZdyListView(Context context, AttributeSet attrs) {
25         super(context, attrs);
26         initView(context);
27     }
28 
29     public ZdyListView(Context context, AttributeSet attrs, int defStyle) {
30         super(context, attrs, defStyle);
31         initView(context);
32     }
33 
34     private void initView(Context context) {
35         footer=inflater.from(context).inflate(R.layout.layout_util_footer, null);
36         this.setOnScrollListener(this);
37         this.addFooterView(footer);
38         this.removeFooterView(footer);
39     }
40 
41     @Override
42     public void onScroll(AbsListView view, int firstVisibleItem,
43             int visibleItemCount, int totalItemCount) {
44         this.lastVisibleItem = firstVisibleItem + visibleItemCount;
45         this.totalItemCount = totalItemCount;
46     }
47 
48     @Override
49     public void onScrollStateChanged(AbsListView view, int scrollState) {
50         //listview item总数量等于最后一个可见的item并且ListView停下不动了
51         if (totalItemCount == lastVisibleItem&& scrollState == SCROLL_STATE_IDLE) {
52             if (!isLoading) {
53                 isLoading = true;
54                 this.addFooterView(footer);
55                 if (refleshDatas != null) {      
56                     //回调执行向服务器端请求数据
57                     refleshDatas.onLoading();
58                 }  
59             }
60         }
61     };
62     public void loadComplete() {
63         isLoading = false;
64         this.removeFooterView(footer);//加载完毕,移除footView;
65     }
66     public void setInterface(RefleshDatas refleshDatas) {
67         this.refleshDatas = refleshDatas;
68     }
69     public interface RefleshDatas{
70         public void onLoading();
71     }
72 }

MainActivity

  1 package com.example.listviewdynamicloading;
  2 
  3 import java.util.ArrayList;
  4 
  5 import com.example.listviewdynamicloading.ZdyListView.RefleshDatas;
  6 
  7 import android.app.Activity;
  8 import android.os.Bundle;
  9 import android.os.Handler;
 10 import android.os.Message;
 11 import android.view.Menu;
 12 import android.view.MenuItem;
 13 import android.widget.ListView;
 14 import android.widget.Toast;
 15 
 16 public class MainActivity extends Activity{
 17     //一次从服务器端请求十条数据
 18     private int current=1;  
 19     private int number=9;
 20     
 21     
 22     private ZdyListView listView; //自定义ListView,将footview,滑动监听等集合在一起,免得Activity代码过多
 23     private ArrayList<String> listDatas;
 24     private ListViewAdapter adapter;
 25 
 26 
 27     private Handler handler=new Handler(){
 28         public void handleMessage(android.os.Message msg) {
 29             switch (msg.what) {
 30             case 0x123:
 31                 setlistView((ArrayList<String>)msg.obj,"firstLoading");//firstLoading标志位代表数据是初次加载的
 32                 break;
 33             case 0x234:
 34                 setlistView((ArrayList<String>)msg.obj,"addLoading");//addLoading标志位代表数据是初次加载之后请求服务器所得
 35                 break;
 36             case 0x345:
 37                 showMsg((String)msg.obj);
 38                 break;
 39             default:
 40                 break;
 41             }
 42         };
 43     };
 44 
 45     @Override
 46     protected void onCreate(Bundle savedInstanceState) {
 47         super.onCreate(savedInstanceState);
 48         setContentView(R.layout.activity_main);
 49         listDatas=new ArrayList<String>();
 50         listView=(ZdyListView) this.findViewById(R.id.listview);
 51         listView.setInterface(new RefleshDatas() {
 52             @Override
 53             public void onLoading() {
 54                 getDataThread(current, current+number, "addLoading");
 55             }
 56         });
 57     }
 58 
 59 
 60 
 61     @Override
 62     protected void onStart() {
 63         super.onStart();
 64         getDataThread(current,number,"firstLoading");
 65     }
 66 
 67     //.........................模拟开启线程向服务器请求数据.....................................
 68     private void getDataThread(final int current, final int number,final String type) {
 69         final Message msg=new Message();
 70         new Thread(){
 71             public void run() {
 72                 ArrayList<String> datas=ListViewDatas.returnNum(current, current+number);
 73                 if(datas!=null&&datas.size()>0){
 74                     switch (type) {
 75                     case "firstLoading":
 76                         msg.what=0x123;
 77                         break;
 78                     case "addLoading":
 79                         msg.what=0x234;
 80                         break;
 81                     default:
 82                         break;
 83                     }    
 84                     msg.obj=datas;
 85                 }else {
 86                     msg.what=0x345;
 87                     msg.obj=datas;
 88                 }
 89                 handler.sendMessage(msg);
 90             };
 91         }.start();
 92     }
 93 
 94 
 95 
 96     private void setlistView(ArrayList<String> datas,String type) {
 97         listDatas.addAll(datas);
 98         if(type.equals("firstLoading")){//初次加载
 99             adapter=new ListViewAdapter(MainActivity.this, listDatas);
100             current=adapter.getCount()+1;
101             listView.setAdapter(adapter);
102             listView.loadComplete();
103         }else if(type.equals("addLoading")){//初次加载后请求的数据,执行notifyDataSetChanged();
104             adapter.notifyDataSetChanged();
105             current=adapter.getCount()+1;
106             listView.loadComplete();
107         }
108     }
109 
110 
111     protected void showMsg(String str) {
112         Toast.makeText(MainActivity.this, "已加载完毕", Toast.LENGTH_SHORT).show();
113         listView.loadComplete();
114     }
115 
116 
117 
118 }

模拟服务器端数据

 1 package com.example.listviewdynamicloading;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class ListViewDatas {
 6     //模拟服务器端数据库中的数据,假设现在只有3条数据
 7     public static int NUM=53;
 8     public static ArrayList<String> returnNum(int startNum,int endNum){
 9         ArrayList<String> list=new ArrayList<String>();
10         if(endNum<=NUM){//客户端请求的数据在数据库数据范围之内
11             for(int i=startNum;i<=endNum;i++){
12                 list.add(String.valueOf(i));
13             }
14             return list;
15         }else if(endNum>=NUM&&startNum<=NUM){//客户端请求的数据不全在数据库数据范围之内
16             for(int i=startNum;i<=NUM;i++){
17                 list.add(String.valueOf(i));
18             }
19             return list;            
20         }else if(startNum>NUM){//客户端请求的数据超出数据库数据范围之内
21             return null;
22         }
23         return null;
24     }
25 }

ListView适配器

 1 package com.example.listviewdynamicloading;
 2 
 3 import java.util.ArrayList;
 4 
 5 import android.content.Context;
 6 import android.view.LayoutInflater;
 7 import android.view.View;
 8 import android.view.ViewGroup;
 9 import android.widget.BaseAdapter;
10 import android.widget.TextView;
11 
12 public class ListViewAdapter extends BaseAdapter{
13     private Context context;
14     private ArrayList<String> datas;
15 
16     public ListViewAdapter(Context context,ArrayList<String> datas){
17         this.context=context;
18         this.datas=datas;
19     }
20     
21     @Override
22     public int getCount() {
23         return datas.size();
24     }
25 
26     @Override
27     public Object getItem(int position) {
28         return null;
29     }
30 
31     @Override
32     public long getItemId(int position) {
33         return position;
34     }
35 
36     @Override
37     public View getView(int position, View convertView, ViewGroup parent) {
38         ViewHolder vh=null;
39         if(convertView==null){
40             vh=new ViewHolder();
41             convertView=LayoutInflater.from(context).inflate(R.layout.listview_item, null);
42             vh.tv=(TextView) convertView.findViewById(R.id.tv);
43             convertView.setTag(vh);
44         }else {
45             vh=(ViewHolder) convertView.getTag();
46         }
47         vh.tv.setText("这是第"+datas.get(position)+"条数据");
48         return convertView;
49     }
50     
51     
52     
53     class ViewHolder{
54         TextView tv;
55     }
56 
57 
58 }