当有大量的数据需要加载到ListView的Adapter中时,全部一次性加载,通常会非常耗时,这将严重影响用户的体验性和流畅性,而分页加载则会优化加载的速度,先暂时显示一页能够显示的数据项,在拖动到最下方时或点击了“显示更多”按钮时,再加载部分(需要自己定义每次显示多少)数据项。
而且此项技术,会在以后的运用中比较常用的使用到。
步骤一:设计主界面布局
mail.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <ListView
- android:id="@+id/listview"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- />
- </LinearLayout>
为了测试,界面比较简单,就一个ListView。
步骤二:设计Adapter中每一项Item的布局
items.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <TextView
- android:id="@+id/bigtext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="15pt"
- />
- <TextView
- android:id="@+id/smalltext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/bigtext"
- android:textSize="7pt"
- />
- </RelativeLayout>
也是比较简单,就是两个TextView相对上下显示
步骤三:(重要)在Activity里设计代码
ShowItemsByPage.java
下面是定义的变量和onCreate函数
- <span style="white-space:pre"> </span>private ListView mListView = null;
- private SimpleAdapter adapter = null;
- private ArrayList<Map<String, String>> dataList = null;
- private final int maxShowItems = 100; // 最多的加载项数目
- private final int stepShowItems = 10; // 每次加载的数目
- private int lastShowItem = 0; // 最后加载的项目
- private Handler mHanlder = null; // 控制发布消息队列
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- mListView = (ListView)findViewById(R.id.listview);
- dataList = new ArrayList<Map<String, String>>();
- mHanlder = new Handler();
- for(int i=0; i<10; i++)
- {
- HashMap<String, String> map = new HashMap<String, String>();
- map.put("big", "大字体加载第" + i + "个选项");
- map.put("small", "小字体加载第" + i + "个选项");
- dataList.add(map);
- }
- // 设置ListView的Adapter
- adapter = new SimpleAdapter(this, dataList, R.layout.items, new String[]{"big", "small"}, new int[]{R.id.bigtext, R.id.smalltext});
- mListView.setAdapter(adapter);
- <strong><span style="color:#ff0000;">mListView.setOnScrollListener(new mOnScrollListener());</span></strong>
- }
在for循环中,为了配合模拟器的显示,显式的要求初始时只先显示10个选项。
在for循环里,每次都定义一个HashMap对象,加载两个文本。
下面是loadData方法
- public void loaddata()
- {
- <span style="color:#ff0000;">int curCount = mListView.getAdapter().getCount();</span>
- Log.i("carter", "当前Adapter的数量为: " + curCount);
- <span style="color:#ff0000;">if( (curCount+stepShowItems)<=maxShowItems )</span>
- {
- <span style="color:#ff0000;">for(int i=curCount; i<(curCount+stepShowItems); i++)</span>
- {
- HashMap<String, String> map = new HashMap<String, String>();
- map.put("big", "大字体加载第" + i + "个选项");
- <span style="white-space:pre"> </span>map.put("small", "小字体加载第" + i + "个选项");
- <span style="white-space:pre"> </span>dataList.add(map);
- }
- }
- else
- {
- <span style="color:#ff0000;">for(int i=curCount; i<maxShowItems; i++)</span>
- {
- HashMap<String, String> map = new HashMap<String, String>();
- map.put("big", "大字体加载第" + i + "个选项");
- <span style="white-space:pre"> </span>map.put("small", "小字体加载第" + i + "个选项");
- <span style="white-space:pre"> </span>dataList.add(map);
- }
- }
- }
这个函数主要是加载分页的数据项到ArrayList中
首先从Adapter中获取当前已经加载的数据项数目curCount,接下来的判断中,如果当前数据项curCount加上每次递进的数据项数目stepShowItems小于等于最大能加载的数据项数目maxShowItems,则把下一页的stepShowItems个数据项加入到ArrayList中,如果超过了maxShowItems,则只把剩余的几项加入到ArrayList中
下面是实现了android.widget.AbsListView.OnScrollListener接口的mOnScrollListener类
- private class mOnScrollListener implements OnScrollListener
- {
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
- // TODO Auto-generated method stub
- Log.i("carter", "onScroll");
- <span style="white-space:pre"> </span><span style="color:#ff0000;">//这里的算数逻辑可能有问题,请自行思考
- lastShowItem = firstVisibleItem + visibleItemCount;</span>
- Log.i("carter", "lastShowItem = " + lastShowItem);
- Log.i("carter", "visibleItemCount = " + visibleItemCount);
- <span style="color:#ff0000;">if(lastShowItem == maxShowItems)</span>
- {
- Toast.makeText(ShowItemsByPages.this, "加载完成", Toast.LENGTH_SHORT).show();
- }
- }
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- // TODO Auto-generated method stub
- Log.i("carter", "onScrollStateChanged");
- Log.i("carter", "scrollState = " + scrollState);
- Log.i("carter", "adapter count = " + mListView.getAdapter().getCount());
- <span style="color:#ff0000;">if( (OnScrollListener.SCROLL_STATE_IDLE==scrollState) &&
- (lastShowItem==(mListView.getAdapter().getCount())) )</span>
- {
- ShowItemsByPages.this.mHanlder.post(new Runnable(){
- public void run()
- {
- <span style="white-space:pre"> </span><span style="color:#ff0000;"><strong>ShowItemsByPages.this.loaddata();
- <span style="white-space:pre"> </span> ShowItemsByPages.this.adapter.notifyDataSetChanged();</strong></span>
- }
- });
- }
- }
- }
mOnScrollListener实现了OnScrollListener接口,必须实现onScroll和onScrollStateChanged方法。
在onScroll方法中,通过方法自带的两个参数firstVisibleItem和visibleItemCount的和计算出当前显示的最后一个数据项lastShowItem,如果最后一个数据项等于最大能显示的数据项时,则说明已经全部加在完成了,弹出提示
在onScrollStateChanged方法中,主要完成拖动到列表最下方自动加在下一页数据项的功能。通过判断当前拖动的状态,和最后显示项和adapter显示项的判断,来确定是否加载下一页。如果可以加载,则用Handler的post一个Runnable到消息队列,通过loadData把数据项加载到ArrayList中,在通过Adapter的notifyDataSetChanged方法,重新加载数据项。
至此,就可以完成这个分页显示的功能了。
http://blog.youkuaiyun.com/carterjin/article/details/7508597