欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

仿知乎应用(3):如何使用Volley和PullToRefreshListView来解析JSON并从Web Service获取数据?

最编程 2024-02-15 12:54:39
...


       我们已经实现了侧滑菜单的切换与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"}]
    1.  

    好,我们来看一下,如何读取这个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.
          1. 显示的结果图:  



          仿知乎程序(三)读取webService,解析json,volley以及PullToRefreshListView的使用_Pic

          在这里,要说明的一点是PullToRefreshListView控件的setOnRefreshListener方法, 它里面有两个实现方法, 一个是我们在程序中所使用的


          new PullToRefreshBase.OnRefreshListener2<ListView>()方法, 这个是既有上拉,又有下拉的方法,还有一个是


          new PullToRefreshBase.OnRefreshListener<ListView>()方法,这个是只有上拉


          可通过这个blog了解更细的使用说明