http://blog.csdn.net/liuhe688/article/details/6852523


熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最重要的组件,我们今天就要讲一讲列表组件ListView加载数据的相关内容。通常来说,一个应用在展现大量数据时,不会将全部的可用数据都呈现给用户,因为这不管对于服务端还是客户端来说都是不小的压力,因此,很多应用都是采用分批次加载的形式来获取用户所需的数据。比如:微博客户端可能会在用户滑动至列表底端时自动加载下一页数据,也可能在底部放置一个“加载更多”按钮,用户点击后,加载下一页数据。

我们今天就结合实例来演示一下使用ListView获取数据的过程。

新建一个loadmore项目,我们来看一下结构图和最终效果图:

左图中包含了三个布局文件、一个Adapter和一个Activity,右图是我们运行后的主界面。

其中,main.xml是主界面的布局文件,它包含一个ListView组件,代码如下:

[html] view plain copy
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:paddingLeft="3dp"
  7. android:paddingRight="3dp">
  8. <ListView
  9. android:id="@id/android:list"
  10. android:layout_width="fill_parent"
  11. android:layout_height="wrap_content"/>
  12. </LinearLayout>
这里我们引用了Android内置的名为list的id,因为我们后面要使用到ListActivity,我们的MainActivity继承于它。

然后就是list_item.xml,它是ListView中单个列表项的布局文件,从效果图中可以看到,这里只使用到了一个TextView组件,list_item.xml代码如下:

[html] view plain copy
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent">
  6. <TextView
  7. android:id="@+id/list_item_text"
  8. android:layout_width="fill_parent"
  9. android:layout_height="fill_parent"
  10. android:gravity="center"
  11. android:textSize="20sp"
  12. android:paddingTop="10dp"
  13. android:paddingBottom="10dp"/>
  14. </LinearLayout>
我们注意到在右图中列表底部有一个按钮不同于其他的列表项,这是什么情况?事实上这个按钮是我们在ListView底部添加的一个视图。ListView组件提供了两个很实用的功能,那就是可以在顶部和底部添加自定义的视图。我们在此处ListView的底部添加了一个视图用来加载更多数据,这个视图对应着load_more.xml布局文件,代码如下:

[html] view plain copy
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:orientation="vertical"
  5. android:layout_width="fill_parent"
  6. android:layout_height="wrap_content">
  7. <Button
  8. android:id="@+id/loadMoreButton"
  9. android:layout_width="fill_parent"
  10. android:layout_height="wrap_content"
  11. android:text="loadmore"
  12. android:onClick="loadMore"/>
  13. </LinearLayout>
接下来我们来了解一下我们的Adapter,ListViewAdapter代码如下:

[java] view plain copy
  1. packagecom.scott.loadmore;
  2. importjava.util.List;
  3. importandroid.content.Context;
  4. importandroid.view.LayoutInflater;
  5. importandroid.view.View;
  6. importandroid.view.ViewGroup;
  7. importandroid.widget.BaseAdapter;
  8. importandroid.widget.TextView;
  9. publicclassListViewAdapterextendsBaseAdapter{
  10. privateList<String>items;
  11. privateLayoutInflaterinflater;
  12. publicListViewAdapter(Contextcontext,List<String>items){
  13. this.items=items;
  14. inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  15. }
  16. @Override
  17. publicintgetCount(){
  18. returnitems.size();
  19. }
  20. @Override
  21. publicObjectgetItem(intposition){
  22. returnitems.get(position);
  23. }
  24. @Override
  25. publiclonggetItemId(intposition){
  26. returnposition;
  27. }
  28. @Override
  29. publicViewgetView(intposition,Viewview,ViewGroupparent){
  30. if(view==null){
  31. view=inflater.inflate(R.layout.list_item,null);
  32. }
  33. TextViewtext=(TextView)view.findViewById(R.id.list_item_text);
  34. text.setText(items.get(position));
  35. returnview;
  36. }
  37. /**
  38. *添加列表项
  39. *@paramitem
  40. */
  41. publicvoidaddItem(Stringitem){
  42. items.add(item);
  43. }
  44. }
这个ListViewAdapter是我们自定义适配器,它继承自BaseAdapter,实例化此适配器需要一个Context对象来获取LayoutInflater实例和一个集合对象来充当适配器的数据集;在getView方法中我们填充list_item.xml布局文件,完成列表每一项的数据显示;addItem方法用来在加载数据时向数据集中添加新数据。

最后我们来看一下MainActivity:

[java] view plain copy
  1. packagecom.scott.loadmore;
  2. importjava.util.ArrayList;
  3. importandroid.app.ListActivity;
  4. importandroid.os.Bundle;
  5. importandroid.os.Handler;
  6. importandroid.util.Log;
  7. importandroid.view.View;
  8. importandroid.widget.AbsListView;
  9. importandroid.widget.AbsListView.OnScrollListener;
  10. importandroid.widget.Button;
  11. importandroid.widget.ListView;
  12. publicclassMainActivityextendsListActivityimplementsOnScrollListener{
  13. privateListViewlistView;
  14. privateintvisibleLastIndex=0;//最后的可视项索引
  15. privateintvisibleItemCount;//当前窗口可见项总数
  16. privateListViewAdapteradapter;
  17. privateViewloadMoreView;
  18. privateButtonloadMoreButton;
  19. privateHandlerhandler=newHandler();
  20. @Override
  21. publicvoidonCreate(BundlesavedInstanceState){
  22. super.onCreate(savedInstanceState);
  23. setContentView(R.layout.main);
  24. loadMoreView=getLayoutInflater().inflate(R.layout.load_more,null);
  25. loadMoreButton=(Button)loadMoreView.findViewById(R.id.loadMoreButton);
  26. listView=getListView();//获取id是list的ListView
  27. listView.addFooterView(loadMoreView);//设置列表底部视图
  28. initAdapter();
  29. setListAdapter(adapter);//自动为id是list的ListView设置适配器
  30. listView.setOnScrollListener(this);//添加滑动监听
  31. }
  32. /**
  33. *初始化适配器
  34. */
  35. privatevoidinitAdapter(){
  36. ArrayList<String>items=newArrayList<String>();
  37. for(inti=0;i<10;i++){
  38. items.add(String.valueOf(i+1));
  39. }
  40. adapter=newListViewAdapter(this,items);
  41. }
  42. /**
  43. *滑动时被调用
  44. */
  45. @Override
  46. publicvoidonScroll(AbsListViewview,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount){
  47. this.visibleItemCount=visibleItemCount;
  48. visibleLastIndex=firstVisibleItem+visibleItemCount-1;
  49. }
  50. /**
  51. *滑动状态改变时被调用
  52. */
  53. @Override
  54. publicvoidonScrollStateChanged(AbsListViewview,intscrollState){
  55. intitemsLastIndex=adapter.getCount()-1;//数据集最后一项的索引
  56. intlastIndex=itemsLastIndex+1;//加上底部的loadMoreView项
  57. if(scrollState==OnScrollListener.SCROLL_STATE_IDLE&&visibleLastIndex==lastIndex){
  58. //如果是自动加载,可以在这里放置异步加载数据的代码
  59. Log.i("LOADMORE","loading...");
  60. }
  61. }
  62. /**
  63. *点击按钮事件
  64. *@paramview
  65. */
  66. publicvoidloadMore(Viewview){
  67. loadMoreButton.setText("loading...");//设置按钮文字loading
  68. handler.postDelayed(newRunnable(){
  69. @Override
  70. publicvoidrun(){
  71. loadData();
  72. adapter.notifyDataSetChanged();//数据集变化后,通知adapter
  73. listView.setSelection(visibleLastIndex-visibleItemCount+1);//设置选中项
  74. loadMoreButton.setText("loadmore");//恢复按钮文字
  75. }
  76. },2000);
  77. }
  78. /**
  79. *模拟加载数据
  80. */
  81. privatevoidloadData(){
  82. intcount=adapter.getCount();
  83. for(inti=count;i<count+10;i++){
  84. adapter.addItem(String.valueOf(i+1));
  85. }
  86. }
  87. }
如代码所示,我们在onCreate方法被调用时获取listView组件,设置其底部视图为loadMoreView,它包含一个按钮,点击时会触发loadMore方法调用,另外在为listView设置完适配器时,又为其设置了滑动事件监听器,滑动列表时onScroll会被调用,滑动状态改变时onScrollStateChanged会被调用。

我们来演示一下这个加载过程:


如图,当点击完按钮后,出现加载动作,加载完之后如右图所示,新数据紧接在原数据之后。然后我们滑动到底部,加载按钮仍可工作:


最后,我们测试一下滑动列表到底部,然后松开,控制台打印如下:


我们看到onScrollStateChanged方法里的if语句里代码执行了,所以如果我们希望自动加载的话,可以把加载代码放于此处。

今天先讲到这里,谢谢大家。


更多相关文章

  1. 内容提供者相关技术
  2. Android(安卓)SparseArray 分析
  3. Android(安卓)之 SQLite简介
  4. 使用android快速开发框架afinal的FinalDb操作android数据库
  5. Android:数据存取之Preferences
  6. Android中SQLite应用详解
  7. android view滑动助手类OverScroller
  8. Android实现录屏直播+远程控制之MediaCodec编码篇
  9. mybatisplus的坑 insert标签insert into select无参数问题的解决

随机推荐

  1. .net程序员转战android第二篇---牛刀小试
  2. 解读新一代岗位要求(一) ----------------A
  3. Android(安卓)Animation学习笔记
  4. android TextView属性大全
  5. React-Native之android集成支付宝
  6. Android开发:使用Fragment改造TabActivity
  7. android studio中光线传感器解析
  8. android_camera_002
  9. android 流量统计实现思路
  10. Android中去除标题,全屏,获得屏幕方向及键