仿知乎应用(3):如何使用Volley和PullToRefreshListView来解析JSON并从Web Service获取数据?
我们已经实现了侧滑菜单的切换与toolbar菜单根据不同页面显示不同工具的功能,今天我们就来完成首页的显示。知乎首页有这么几个功能:
1,列表功能,信息是以列表的形式展示出来的
2,列表要能实现下拉刷新,上拉加载的功能
3,图片与文字并存
4,点击其中一项的不同区域,会跳到不同的详细页面,点击标题会跳动到一个页面,点击下面信息概要又会跳到另一个页面
好,我们就来实现这四个功能。
这里的信息,我是通过读取服务器上webService传过来的json数据,进行解析来当信息源的。所以我们先要把信息源从服务器读出来,才能进行下面的操作。在做这之前,我们先看一下这个首页都有哪些项,有一个用户的图片,一个标题,一个信息的大小,和信息的内容。为了能更好的进行将信息读取,我们先建一个model类,把相关的字段先加上。代码如下:
IndexList.Java
1. /**
2. * 用于显示在index_fragment中ListView的内容
3. * Created by cg on 2015/10/29.
4. */
5. public class
6. private int questionID; //问题ID
7. private String questionTitle; //问题标题
8. private String questionSize; //问题点在字节数
9. private String questionContent; //问题内容
10. private String userPic; //发问者头像
11.
12. public
13. }
14.
15. public IndexList(int
16. this.questionID = questionID;
17. this.questionTitle = questionTitle;
18. this.questionSize = questionSize;
19. this.questionContent = questionContent;
20. this.userPic = userPic;
21. }
22.
23. public int
24. return
25. }
26.
27. public void setQuestionID(int
28. this.questionID = questionID;
29. }
30.
31. public
32. return
33. }
34.
35. public void
36. this.questionTitle = questionTitle;
37. }
38.
39. public
40. return
41. }
42.
43. public void
44. this.questionSize = questionSize;
45. }
46.
47. public
48. return
49. }
50.
51. public void
52. this.questionContent = questionContent;
53. }
54.
55. public
56. return
57. }
58.
59. public void
60. this.userPic = userPic;
61. }
62. }
好,model类我们建好了,现在我们就要从webServies开始取数据了,android读取webServies有很多好的第三方插件,这里我使用的是Ksoap2-android,它的使用网上有很多,我就不多说了,https://github.com/simpligility/ksoap2-android可以去下载,下载之后,我们引入jar.因为这里面我们需要一些常用的变量值,比如说地址什么的,所以我使用一个class,来存这些常用变量
configStatic.java
1. /**
2. * 常量信息
3. * Created by cg on 2015/10/29.
4. */
5. public class
6. /**
7. * webServies地址的命名空间,域名
8. */
9. public static String WEBSERVIESNAMESPACE = "http://tempuri.org/";
10.
11. /**
12. * webServies明确地址
13. */
14. public static String WEBSERVIESURL = "http://192.168.0.163:8090/webServices/questionInfo.asmx";
15.
16. /**
17. * webServices的方法名_用来提取10条问题
18. */
19. public static String WEBSERVICES_INDEXLIST = "getQuestionList";
20. }
这里的地址是我本地的地址,下面是它传回来的数据格式:
1. [{"questionID":28,"questionTitle":"苍井空老师的个人简介","questionSize":"387","questionContent":"\r\n 苍井空,1983年11月11日出生于日本东京。日本AV女演员、
2. 成人模特,兼电视、电影演员。日本女子组合惠比寿麝香葡萄的初代首领,现成员、OG首领。2010年3月毕业并将组合首领之位交托给麻美由真,同年10月复归。
3. \r\n 入行前曾是泳装写真女星,2002年进入AliceJapan公司,开始性感影片的拍摄生涯。因为其“童颜巨乳”的特色,开始获得人气,并连续在2003年及2004年蝉联日本
4. 《VideoBoy》杂志年度性感女艺人第一名。[1] 从2003年起,开始参加一般电视戏剧及综艺节目中演出,[2] 2004年11月移籍到S1,成功转型,大牌杂志模特及电影演员。
5. \r\n","userPic":"http://imgcdn.kdnet.net/UploadSmall/2013/07/21/137438445351976.jpg"},{"questionID":27,"questionTitle":"波多野结衣的故事",
6. "questionSize":"679","questionContent":"波多野结衣(はたの ゆい),女,1988年5月24日出生于日本京都府,著名日本女演员、AV女优。
7. 2008年,波多野结衣开始从事AV出演,并于11月加入H.M.P公司,成为H.M.P的素人,不久便被H.M.P公司雪藏,随后在BeFree公司发行过两部影片,
8. 又转投ATTACKER公司,后又签约SKY HIGH公司。2012年,波多野结衣出席第九届上海国际成人展开幕和第二届*成人博览会。",
9. "userPic":"http://img1.imgtn.bdimg.com/it/u=1823077414,3028399801\u0026fm=21\u0026gp=0.jpg"}]
好,我们来看一下,如何读取这个webService:
webservicesUntils.java
1. import
2. import
3. import
4. import
5. import
6.
7. import
8.
9. /**
10. * webservice 操作类
11. * Created by cg on 2015/10/29.
12. */
13. public class
14. private static SoapObject rpc = null;
15. private static SoapSerializationEnvelope envelope = null;
16. private static HttpTransportSE ht = null;
17.
18. /**
19. * 调用问题信息
20. * @param strWhere 查询条件
21. * @param orderby 排序字段
22. * @param startIndex 开始记录数
23. * @param endIndex 结束记录数
24. * @return
25. * @throws Exception
26. */
27. public static String getIndexItemList(final String strWhere,final String orderby,final int startIndex,final int endIndex) throws
28.
29. new
30. // 设置调用方法参数的值
31. "strWhere", strWhere);
32. "orderby", orderby);
33. "startIndex", startIndex);
34. "endIndex",endIndex);
35.
36. // 生成调用Webservice方法的SOAP请求信息
37. new SoapSerializationEnvelope(SoapEnvelope.VER12); //这里要注意,这里是webService的版本号,一般是10,11,12这三个值,如果你不确定,可以每个都试一下
38. envelope.bodyOut = rpc;
39. true;
40. envelope.setOutputSoapObject(rpc);
41. // 创建HttpTransportSE对象,通过HttpTransportSE类的构造方法可以指定WebService的url
42. new
43. true;
44. // 使用call方法调用WebService方法
45.
46. null, envelope);
47.
48. "0";
49.
50. //检查ht.call是否运行
51. //Log.e("city", strWhere + startIndex + endIndex);
52.
53. // 判断取到的值是否为空
54. if(envelope.getResponse() == null) {
55. "0";
56. else{
57. result = envelope.getResponse().toString();
58. }
59.
60. return
61. }
62. }
要想让它好用,我们还要给它添加
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />权限
这里就不多说了,上面的注解比较清楚,通过webservice我们已经把要得到的数据取回来了,接下来,我们就要把数据显示出来。这种列表形式的显示我们一般都是采用ListView控件来展示,可是我们结合第二点的需求,就是需求一个上拉和下拉的需求,这个功能ListView是没有,我们只能继承ListView自己写控件,可是自己写有点麻烦了,还好有这方面的第三插件,当然了,google也发布了一个官方的SwipeRefreshLayout插件,虽然很不错,可是它只有下拉刷新,没有上拉加载的功能。所以这里我们使用PullToRefreshListView控件,https://github.com/chrisbanes/Android-PullToRefresh,大家可以去这里下载,可惜的是,它没有给android studio提供直接加载的链接,我们直接采用加载project的方式,来加载它。好了,我们来修改一下我们之前的fragment_index.xml文件
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:layout_width="match_parent"
4. android:layout_height="match_parent">
5.
6. <!--
7. ptr:ptrMode:PullToRefreshListView设置向上拉刷新还是向下拉刷新模式
8. PULL_FROM_END: 下拉刷新
9. PULL_FROM_START: 上拉加载
10. both: 下拉刷新和上拉加载都有
11. >
12. <com.handmark.pulltorefresh.library.PullToRefreshListView
13. xmlns:ptr="http://schemas.android.com/apk/res-auto"
14. android:id="@+id/pullrefresh_index_list"
15. android:layout_width="fill_parent"
16. android:layout_height="fill_parent"
17. android:cacheColorHint="#00000000"
18. android:divider="@color/grey"
19. android:dividerHeight="1dp"
20. android:fadingEdge="none"
21. android:fastScrollEnabled="false"
22. android:footerDividersEnabled="false"
23. android:headerDividersEnabled="false"
24. android:smoothScrollbar="true"
25. ptr:ptrMode="both">
26. </com.handmark.pulltorefresh.library.PullToRefreshListView>
27.
28. </LinearLayout>
PullToRefreshListView控件的使用与ListView控件的使用大体相当,没什么特别的地方,就是加载Adapter然后显示出来,但是它多了两个方法,
1. public void
2. // 模拟加载任务
3.
4. }
5.
6. @Override
7. public void
8.
9.
10. }
是用来实现上拉加载,下拉刷新的,而且都是要通过异步来进行加载的。好了,我们来修改一下首页的java代码吧
1. import
2. import
3. import
4. import
5. import
6. import
7. import
8. import
9. import
10. import
11. import
12.
13. import
14. import
15. import
16. import
17.
18. /**
19. * 首页
20. * Created by cg on 2015/10/27.
21. */
22. public class IndexFragment extends
23.
24. //定义信息等等控件
25. private
26. private PullToRefreshListView pullrefresh_index_list; //定义信息列表
27. @Override
28. public
29. Bundle savedInstanceState) {
30. false);
31. initControls(view);
32. return
33. }
34. /**
35. * 对下拉列表控件进行初始化,并初始化进度控件
36. * @param view
37. */
38. private void
39.
40. pullrefresh_index_list = (PullToRefreshListView)view.findViewById(R.id.pullrefresh_index_list);
41.
42. //初始化数据
43. initDatas();
44.
45. // 设置下拉和上拖监听事件
46. pullrefresh_index_list
47. new
48. @Override
49. public void
50. // 模拟加载任务
51. //new GetDownDataTask().execute();
52. }
53.
54. @Override
55. public void
56. //Log.e("onPullUpToRefresh","有反应没有啊");
57. //new GetUpDataTask().execute();
58. }
59.
60. });
61.
62. }
63.
64. /**
65. * 初始时,加载10条数据上来
66. */
67. private void
68. {
69. if(netUntils.isNetworkAvailable(getActivity())) {
70. // 初始化数据和数据源
71. new
72. //设置风格为圆形进度条
73. "提示"); //设置标题
74. "数据加载中,请稍等..."); //设置内容
75. false); //设置进度是否为不明确
76. true); //设置进度条是否可以按退回键取消
77. myProgressDialog.show();
78.
79. new Thread(new
80. @Override
81. public void
82. new
83.
84. try
85. "", "", 1, 10);
86.
87. "soapObject",soapObject);
88.
89.
90. 1;
91.
92. handler.sendMessage(msg);
93.
94. catch
95. 2;
96. }
97. }
98. }).start();
99. else
100. {
101. "请检查您的网络是否打开!", Toast.LENGTH_LONG).show();
102. }
103.
104. }
105.
106. new
107.
108. @Override
109. public void
110. if(msg.arg1==1)
111. {
112. //Log.e("")
113.
114. else
115. {
116. "数据读取失败!", Toast.LENGTH_LONG).show();
117. }
118.
119. myProgressDialog.dismiss();
120. }
121. };
122. }
简单对程序说一下,这里我们只是简单的实现了一下把webservices中的数据取到,然后用log的方式显示出来,并没有对PullToRefreshListView进行设置什么,因为从网络中读取数据,这是需要时间的,所以我们采用了handle的方式。为了给用户一个更好的用户体验,我们加入了ProgressDialog控件,来显示等待的时间。
我们运行一下,你会发现,我们可以在logcat中显示出相应的信息了。
好,这说明我们的数据读取成功了,下面我们来设置一下列表中各item的布局和为PullToRefreshListView编写一个adapter.
在编写布局之前,我要说明一点,以前我们在做web程序的时候,图片我们都是在数据库中存取的图片地址,而不是采用二进制的形式把图片存在数据库中,这里我们也是采用这种方式,我们去看刚才我给的数据格式,我们的图片,也是一个网络地址,这样的话,就需要我们把这个网络图片显示出来,显示网络图片,用我们常用的ImageView是不行了,处非我们把图片下载到本地,然后再进行加载。现在有一个非常好用的volley,为我们提供了网络加载图片的功能。下面这个blog. ,一共是四篇,非常详细的介绍了它的使用,下载地址:
这里我们用到的是就是其中的NetworkImageView。先把volley.jar导入我们的程序。好了,我们来看一下,item的布局文件
fragment_index_list_item.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:layout_width="match_parent"
4. android:layout_height="match_parent"
5. android:orientation="vertical">
6.
7. <RelativeLayout
8. android:layout_width="fill_parent"
9. android:layout_height="wrap_content"
10. android:layout_marginTop="5dp"
11. android:layout_marginBottom="5dp"
12. android:layout_marginLeft="5dp"
13. android:layout_marginRight="5dp">
14.
15. <TextView
16. android:id="@+id/txt_index_item_Cate"
17. android:layout_width="wrap_content"
18. android:layout_height="wrap_content"
19. android:text="热门话题"
20. android:textSize="@dimen/list_remark_size"
21. android:textColor="@color/gray"/>
22. <com.android.volley.toolbox.NetworkImageView
23. android:id="@+id/netimg_index_item_userpic"
24. android:layout_width="30dp"
25. android:layout_height="30dp"
26. android:src="@drawable/img_empty_followers"
27. android:layout_alignParentRight="true"
28. />
29. </RelativeLayout>
30. <LinearLayout
31. android:id="@+id/linear_index_item_title"
32. android:layout_width="fill_parent"
33. android:layout_height="wrap_content"
34. android:layout_marginTop="5dp"
35. android:layout_marginBottom="5dp"
36. android:layout_marginLeft="5dp"
37. android:layout_marginRight="5dp"
38. android:cacheColorHint="#00000000">
39. <TextView
40. android:id="@+id/txt_index_item_title"
41. android:layout_width="fill_parent"
42. android:layout_height="wrap_content"
43. android:text=" "
44. android:textColor="@color/black"
45. android:textSize="@dimen/ActionBar_title_size"
46. />
47. </LinearLayout>
48. <LinearLayout
49. android:id="@+id/linear_index_item_content"
50. android:layout_width="fill_parent"
51. android:layout_height="wrap_content"
52. android:layout_marginTop="5dp"
53. android:layout_marginBottom="5dp"
54. android:layout_marginLeft="5dp"
55. android:layout_marginRight="5dp"
56. android:cacheColorHint="#00000000"
57. android:background="@drawable/index_list_item_background">
58. <TextView
59. android:id="@+id/txt_index_item_size"
60. android:layout_width="0dp"
61. android:layout_height="wrap_content"
62. android:layout_weight="1"
63. android:duplicateParentState="true"
64. android:background="@drawable/index_list_item_sizebacground"
65. android:text="1324K"
66. android:textSize="@dimen/list_remark_size"
67. android:textColor="@drawable/index_list_item_sizetextcolor"
68. android:layout_marginRight="5dp"
69. android:gravity="center"
70. android:layout_marginTop="2dp"
71. />
72. <TextView
73. android:id="@+id/txt_index_item_content"
74. android:layout_width="0dp"
75. android:layout_height="wrap_content"
76. android:text=" "
77. android:textSize="@dimen/list_remark_size"
78. android:textColor="@drawable/index_list_item_contexttextcolor"
79. android:duplicateParentState="true"
80. android:lines="3"
81. android:ellipsize = "end"
82. android:layout_weight="8"
83. />
84. </LinearLayout>
85.
86. </LinearLayout>
在这里,我为内容布局设置了动态背景还把文字颜色也设置成了动态的,这个是为了在用户点击的时候,达到相应的变化。虽然这个对于功能来说并没有什么卵用。
在drawable/index_list_item_background.xml 代码:
1. <?xml version="1.0" encoding="utf-8"?>
2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
3.
4. <item
5. android:state_activated="true"
6. android:drawable="@color/titleBlue"
7. />
8. <item
9. android:state_focused="false"
10. android:state_pressed="true"
11. android:drawable="@color/titleBlue" />
12. <item android:drawable="@android:color/transparent" />
13. </selector>
index_list_item.sizebacground.xml
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 没有焦点时的背景图片 -->
<item android:state_window_focused="false" android:drawable="@color/titleBlue" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="@color/white" />
<!-- 默认时的背景图片-->
<item android:drawable="@color/white" />
</selector>
这里要注意一点的是,我们一般喜欢设置一下默认的背景图片或是颜色,这里一定要把这个默认的值放在最下面,不然上面的所有变化就都不好用。
index_list_item.contexttextcolor.xml
1. <?xml version="1.0" encoding="utf-8" ?>
2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
3.
4. <!-- 没有焦点时的背景图片 -->
5. <item android:state_window_focused="false" android:color="@color/gray" />
6.
7. <item android:state_focused="false" android:state_pressed="true" android:color="@color/white" />
8. <!-- 默认时的背景图片-->
9. <item android:color="@color/gray" />
10.
11. </selector>
index_list_item_sizetextcolor.xml
1. <?xml version="1.0" encoding="utf-8" ?>
2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
3.
4. <!-- 没有焦点时的背景图片 -->
5. <item android:state_window_focused="false" android:color="@color/white" />
6.
7. <item android:state_focused="false" android:state_pressed="true" android:color="@color/titleBlue" />
8. <!-- 默认时的背景图片-->
9. <item android:color="@color/white" />
10.
11. </selector>
好,item布局文件搞定,我们来看一下Adapter的代码:
Index_lv_Adapter.java
1. import
2. import
3. import
4. import
5. import
6. import
7. import
8. import
9.
10. import
11. import
12. import
13. import
14. import
15. import
16. import
17.
18. import
19.
20. /**
21. * 首页信息列表Adapter
22. * Created by cg on 2015/10/30.
23. */
24. public class Index_lv_Adapter extends
25.
26. private List<IndexList> list_index; //定义显示的信息列表
27. private
28.
29. //定义volley
30. private
31. private
32. private
33.
34. public
35. this.context = context;
36. this.inflater = LayoutInflater.from(context);
37. this.list_index = list_index;
38.
39. mQueue = Volley.newRequestQueue(context);
40. new ImageLoader(mQueue,new
41. @Override
42. public
43. return null;
44. }
45.
46. @Override
47. public void
48.
49. }
50. });
51. }
52.
53. @Override
54. public int
55. return
56. }
57.
58. @Override
59. public Object getItem(int
60. return
61. }
62.
63. @Override
64. public long getItemId(int
65. return
66. }
67.
68. @Override
69. public View getView(final int
70. final
71. if(convertView==null)
72. {
73. new
74. null,false);
75. listclass.userpic = (NetworkImageView)convertView.findViewById(R.id.netimg_index_item_userpic);
76. listclass.item_title = (TextView)convertView.findViewById(R.id.txt_index_item_title);
77. listclass.item_size = (TextView)convertView.findViewById(R.id.txt_index_item_size);
78. listclass.item_content = (TextView)convertView.findViewById(R.id.txt_index_item_content);
79. listclass.linear_index_item_title = (LinearLayout)convertView.findViewById(R.id.linear_index_item_title);
80. listclass.linear_index_item_content = (LinearLayout)convertView.findViewById(R.id.linear_index_item_content);
81.
82. convertView.setTag(listclass);
83. }
84. else
85. {
86. listclass = (index_list_info)convertView.getTag();
87. }
88.
89. //为图片控件加载图片,采用NetworkImageView控件。
90. //第一项是加载图片控件的默认图片,一般是图片加载中,这样的图片
91. //第二项是当发生错误的时候加载的图片,如网络图片路径不对或是加载失败的时候显示的图片
92. //第三项就是加载网络图片了
93. listclass.userpic.setDefaultImageResId(R.drawable.img_empty_followers);
94. listclass.userpic.setErrorImageResId(R.drawable.img_empty_followers);
95. listclass.userpic.setImageUrl(list_index.get(position).getUserPic(), imageLoader);
96.
97. listclass.item_title.setText(list_index.get(position).getQuestionTitle());
98. listclass.item_size.setText(list_index.get(position).getQuestionSize());
99. listclass.item_content.setText(list_index.get(position).getQuestionContent());
100.
101.
102. // 只所以在这里添加点击事件,而不是为控件添加onitemclistener事件,
103. // 是因为,在一个item里,点击上半部分和下半部分将要跳转的页面不同
104. new
105. @Override
106. public void
107. /*Intent cIntent = new Intent();
108. cIntent.setClass(context, Index_detailActivity.class);
109. cIntent.putExtra("questionID", list_index.get(position).getQuestionID());
110. cIntent.putExtra("questionTitle",list_index.get(position).getQuestionTitle());
111. context.startActivity(cIntent);*/
112. }
113. });
114.
115. return
116. }
117.
118.
119. public class
120. {
121. NetworkImageView userpic;
122. TextView item_title;
123. TextView item_size;
124. TextView item_content;
125. LinearLayout linear_index_item_title;
126. LinearLayout linear_index_item_content;
127. }
128. }
这里我把volley处理图片,防止OOM的代码单独拿出来,放到一个公共类里面,供以后的程序的调用。
1. imagesUntils.java
2. import
3. import
4. import
5.
6. import
7. /**
8. * 各种对图片进行操作的通用方法
9. * Created by cg on 2015/10/30.
10. */
11. public class
12. /**
13. * 显示保存在手机中的图片,加入了缩小图片的功能,防止OOM
14. *
15. * @param imgPath 文件路径
16. * @param screenWidth 手机宽
17. * @param screenHeight 手机高
18. * @return Bitmap类型
19. */
20. public static Bitmap viewPic(String imgPath,int screenWidth,int
21. {
22.
23. new
24. true; //不去真的解析图片 获取图片头部信息
25. //取得图片的信息
26. int height = options.outHeight; //图片的高
27. int width = options.outWidth; //图片的宽
28.
29. // 得到手机屏幕宽高比
30. int
31. int
32. int scale=1; //默认缩小比例是1
33. // 如果高的比例大,并且比例大于1,也就是图片的高要大于手机的高
34. if(scaleX>scaleY && scaleY>=1)
35. {
36. scale=scaleX;
37. }
38.
39. if(scaleY>scaleX && scaleX>=1)
40. {
41. scale=scaleY;
42. }
43.
44. false; //真的去解析图片
45. //按比例缩小图片
46. Bitmap bm = BitmapFactory.decodeFile(imgPath, options);
47. return
48. }
49.
50.
51. /**
52. * 对图片进行防OOM处理
53. */
54. public static class BitmapCache implements
55.
56. private
57.
58. public
59. int maxSize = 10*1024*1024;
60. new
61. protected int
62. {
63. return
64. }
65. };
66. }
67.
68. @Override
69. public
70. return
71. }
72.
73. @Override
74. public void
75. mCache.put(url,bitmap);
76. }
77. }
78. }
Adapter程序完成,我们来修改首页的程序,为PullToRefreshListView控件绑定数据。修改后的代码如下:
1. import
2. import
3. import
4. import
5. import
6. import
7. import
8. import
9. import
10. import
11. import
12.
13. import
14. import
15. import
16. import
17. import
18. import
19.
20. import
21. import
22. import
23. import
24.
25. import
26. import
27. import
28.
29. /**
30. * 首页
31. * Created by cg on 2015/10/27.
32. */
33. public class IndexFragment extends
34.
35. //定义信息等等控件
36. private
37. private PullToRefreshListView pullrefresh_index_list; //定义信息列表
38.
39. private List<IndexList> list_index; //定义显示数据的list
40. private Index_lv_Adapter indexAdapter; //定义Adapter
41.
42. @Override
43. public
44. Bundle savedInstanceState) {
45. false);
46. initControls(view);
47. return
48. }
49. /**
50. * 对下拉列表控件进行初始化,并初始化进度控件
51. * @param view
52. */
53. private void
54.
55. pullrefresh_index_list = (PullToRefreshListView)view.findViewById(R.id.pullrefresh_index_list);
56.
57. new
58.
59. //初始化数据
60. initDatas();
61.
62. // 设置下拉和上拖监听事件
63. pullrefresh_index_list
64. new
65. @Override
66. public void
67. // 模拟加载任务
68. new
69. }
70.
71. @Override
72. public void
73. //Log.e("onPullUpToRefresh","有反应没有啊");
74. new
75. }
76.
77. });
78.
79. }
80.
81. /**
82. * 初始时,加载10条数据上来
83. */
84. private void
85. {
86. if(netUntils.isNetworkAvailable(getActivity())) {
87. // 初始化数据和数据源
88. new
89. //设置风格为圆形进度条
90. "提示"); //设置标题
91. "数据加载中,请稍等..."); //设置内容
92. false); //设置进度是否为不明确
93. true); //设置进度条是否可以按退回键取消
94. myProgressDialog.show();
95.
96. new Thread(new
97. @Override
98. public void
99. new
100.
101. try
102.
103. //得到数据
104. "", "", 1, 10);
105.
106. //判断如果数据返回的不是错误代码0,则对返回的json数据进行解析,将数据存入List中
107. if (soapObject != "0") {
108. try
109.
110. new
111.
112. for (int i = 0; i < jsonArray.length(); i++) {
113. JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
114.
115. new
116. "userPic"));
117. "questionTitle"));
118. "questionSize"));
119. "questionContent"));
120. "questionID"));
121.
122. list_index.add(comm);
123. }
124. catch
125. // TODO Auto-generated catch block
126. e.printStackTrace();
127. }
128. }
129.
130.
131.
132. 1;
133.
134. handler.sendMessage(msg);
135.
136. catch
137. 2;
138. }
139. }
140. }).start();
141. else
142. {
143. "请检查您的网络是否打开!", Toast.LENGTH_LONG).show();
144. }
145.
146. }
147.
148. new
149.
150. @Override
151. public void
152. if(msg.arg1==1)
153. {
154. if(list_index!=null)
155. {
156. //设置适配器
157. new
158. pullrefresh_index_list.setAdapter(indexAdapter);
159. else
160. {
161. "无数据加载!", Toast.LENGTH_LONG).show();
162. }
163.
164. else
165. {
166. "数据读取失败!", Toast.LENGTH_LONG).show();
167. }
168.
169. myProgressDialog.dismiss();
170. }
171. };
172.
173. /**
174. * 下拉时,更新数据,从list中提取第一条数据也就是最新的一条,传回,以供判断是否有新的数据,如果有,则对listView进行刷新
175. * 通过return将得到的数据返回给protected void onPostExecute(String result),以便在前台显示
176. */
177. private class GetDownDataTask extends
178. {
179.
180. //异步取数据
181. @Override
182. protected
183. {
184. try
185. {
186. //这里调用一个webServices取新添加的数据
187. //原理:取现在list中最新的数据,去后台数据中进行对比,如果有比这个新的数据,就取,没有则返回0
188. 0).getQuestionID()));
189.
190. return
191. catch
192. e.printStackTrace();
193. catch
194. e.printStackTrace();
195. }
196. return ""
197. }
198.
199. //将数据显示在前台
200. @Override
201. protected void
202. {
203. if(!result.equals("0"))
204. {
205. try
206.
207. //我们采用了.add(location,comm)方法,指定了插入的位置,这样就把新的数据直接插入到前面
208. //list_index.clear(); //清空List<>中的数据
209.
210. new
211.
212. for (int i = 0; i < jsonArray.length(); i++) {
213. JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
214.
215. new
216. "userPic"));
217. "questionTitle"));
218. "questionSize"));
219. "questionContent"));
220. "questionID"));
221.
222. 0,comm);
223.
224. }
225. indexAdapter.notifyDataSetChanged();
226. //num=1;
227. catch
228. // TODO Auto-generated catch block
229. e.printStackTrace();
230. }
231. }
232. //刷新结束,必须加上此句,不然下面的加载图标一下在
233. pullrefresh_index_list.onRefreshComplete();
234. }
235. }
236.
237. /**
238. * 向上刷新加载更多的数据
239. */
240. public class GetUpDataTask extends
241.
242. @Override
243. protected
244.
245. try
246.
247. "", "", list_index.size() + 1, 10);
248.
249. return
250.
251. catch
252. return "0";
253. }
254.
255. }
256.
257. @Override
258. protected void
259. if (result != "0") {
260. try
261.
262. new
263.
264. for (int i = 0; i < jsonArray.length(); i++) {
265. JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
266.
267. new
268. "userPic"));
269. "questionTitle"));
270. "questionSize"));
271. "questionContent"));
272. "questionID"));
273.
274. list_index.add(comm);
275. }
276.
277. indexAdapter.notifyDataSetChanged();
278. catch
279. // TODO Auto-generated catch block
280. e.printStackTrace();
281. }
282. }
283. //刷新结束,必须加上此句,不然下面的加载图标一下在
284. pullrefresh_index_list.onRefreshComplete();
285. }
286.
287. }
288. }
289.
- 显示的结果图:
在这里,要说明的一点是PullToRefreshListView控件的setOnRefreshListener方法, 它里面有两个实现方法, 一个是我们在程序中所使用的
new PullToRefreshBase.OnRefreshListener2<ListView>()方法, 这个是既有上拉,又有下拉的方法,还有一个是
new PullToRefreshBase.OnRefreshListener<ListView>()方法,这个是只有上拉
可通过这个blog了解更细的使用说明