前言:
在开发的过程中,有时候我们需要从网络解析一些数据,比如最近的一些新闻,我们需要把这些数据用ListView显示出来。
因为是解析一个网络数据源,这样将会一下子将所有的数据解析出来,当数据源数据过大时,就可能会造成解析时间过长,占用内存过大等问题。
这时候想到用分页列表来显示这些数据,即每次只显示一个屏幕所能容纳条数的列表项数据,当用户手指向下拉动的时候,才再加载一个屏幕所能容纳的条数的数据,这样就解决了上述问题。
---------------------------------------------------------------------------------------------------------------------------------
思路:
先来看一个数据源地址,内容为某一个城市待出售房屋信息
1 http://ikft.house.qq.com/index.php?guid=866500021200250&devua=appkft_1080_1920_XiaomiMI4LTE_1.8.3_Android19&order=0&searchtype=normal&devid=866500021200250&appname=QQHouse&mod=appkft&act=searchhouse&channel=71&page=1&rn=20&cityid=1
该地址红色部分代表页数,rn=20代表一页有20条相应数据
通过www.bejson.com网站解析该网址相应的JSON数据为XML格式
1 {
2 "retcode": 0,
3 "retmsg": "成功",
4 "total": "817",
5 "page": 1,
6 "rn": 20,
7 "data": [
8 {
9 "fid": "122591",
10 "fcover": "http://p0.qpic.cn/estate/0/cbcef0b36d585650ec602ebe0ca56a18.jpg/180",
11 "fname": "鸿坤·理想湾",
12 "faddress": "涿州东高铁新城涿州东站西侧300米",
13 "fregion": "大北京",
14 "fpricedisplaystr": "7200元/平米",
15 "faroundhighprice": 7500,
16 "faroundlowprice": 6500,
17 "groupbuynum": 3587,
18 "lng": "116.052084096376",
19 "lat": "39.4636526249295",
20 "fsellstatus": "1",
21 "istencentdiscount": 0,
22 "bookmark": [
23 {
24 "tag": "看房团",
25 "type": 2
26 },
27 {
28 "tag": "低总价",
29 "type": 3
30 },
31 {
32 "tag": "品牌开发商",
33 "type": 3
34 }
35 ],
36 "price_pre": "均价",
37 "price_value": "7200",
38 "price_unit": "元/平米",
39 "panoid": "",
40 "heading": "",
41 "pitch": "",
42 "has_agent": 1,
43 "hui": 1
44 },
45
也就是说,当我们解析这个网址的数据时,会有20条数据,当把网址红色部分page=1 --->page=2 时,又将显示20条数据
怎么实现分页列表一次显示20条数据呢?
从数据源网址可以看出一个我们只要把page依次加一,便可以依次加载对应网址数据源了
也就是说,只要把每次加载的数据添加到适配器中,便可以实现分页列表每页每次加载固定个数个数据条
------------------------------------------------------------------------------------------------------------------------------------------------------------
代码:
1、解析房屋信息,我们这里先只获得房屋名字信息放到ListView中
先建一个房屋实体类
1 package com.example.listview;
2
3 public class Home {
4 private String name;
5
6 public Home() {
7 super();
8 // TODO Auto-generated constructor stub
9 }
10
11 public Home(String name) {
12 super();
13 this.name = name;
14 }
15
16 public String getName() {
17 return name;
18 }
19
20 public void setName(String name) {
21 this.name = name;
22 }
23
24 @Override
25 public String toString() {
26 return name;
27 }
28
29 }
Home.class
2、工具类(http获取数据,json数据解析)
1 package com.example.listview;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.net.HttpURLConnection;
7 import java.net.MalformedURLException;
8 import java.net.URL;
9
10 public class HttpUtil {
11 //将指定路径上的数据转换为字节数组形式返回
12 public static byte[] getByteJsonString(String path) throws IOException
13 {
14 URL url = new URL(path);
15 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
16 conn.setRequestMethod("GET"); //Get的连接方式
17 conn.setConnectTimeout(5000);
18 conn.setDoInput(true);
19 if(conn.getResponseCode()==200)// 响应码等于200表示连接成功
20 {
21 InputStream in = conn.getInputStream();
22 return getByteString(in);
23 }
24 return null;
25
26 }
27
28 public static byte[] getByteString(InputStream in) throws IOException
29 {
30 //内存流获取数据
31 ByteArrayOutputStream out = new ByteArrayOutputStream();
32 int len = 0;
33 byte[] b = new byte[1024];
34 while((len = in.read(b))!=-1)
35 {
36 //注意不要写成out.write(b); 否则若字节数据长度大于实际数据长度,后面部分乱码,导致后面json解析出错
37 out.write(b,0,len);
38 }
39
40 return out.toByteArray();
41 }
42
43 }
HttpUtil.class
1 package com.example.listview;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.json.JSONArray;
7 import org.json.JSONException;
8 import org.json.JSONObject;
9
10
11 public class JsonString {
12 public static List getJsonResult(String json) throws JSONException
13 {
14 //JSON解析 ,解析某一城市下所有房屋的名字
15 List<Home> list = new ArrayList<Home>();
16 JSONObject obj = new JSONObject(json);
17 JSONArray arr = obj.getJSONArray("data");
18 Home home = null;
19 for(int i=0;i<arr.length();i++)
20 {
21
22 JSONObject data = arr.getJSONObject(i);
23 home = new Home();
24
25
26 String fname =data.getString("fname");
27 home.setName(fname);
28 list.add(home);
29 }
30 return list;
31
32
33 }
34 }
JsonString.class解析JSON数据
3、ListView的自定义适配器类
1 package com.example.listview;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import android.content.Context;
7 import android.view.LayoutInflater;
8 import android.view.View;
9 import android.view.ViewGroup;
10 import android.widget.BaseAdapter;
11 import android.widget.TextView;
12
13 public class MyAdapter extends BaseAdapter{
14
15 private Context context;
16 private List<Home> list;
17
18 public MyAdapter(Context context)
19 {
20 this.context = context;
21 list = new ArrayList<Home>();
22 }
23 //关键点!
24 //将底部下拉刷新出来的数据(新解析出来的固定条数数据)添加到当前适配器中
25 public void addData(List lists){
26 list.addAll(lists);
27 }
28 @Override
29 public int getCount() {
30 // TODO Auto-generated method stub
31 int count = 0;
32 if(list!=null)
33 return list.size();
34 return count;
35 }
36
37 @Override
38 public Object getItem(int position) {
39 // TODO Auto-generated method stub
40 return list.get(position);
41 }
42
43 @Override
44 public long getItemId(int position) {
45 // TODO Auto-generated method stub
46 return position;
47 }
48
49 @Override
50 public View getView(int position, View convertView, ViewGroup parent) {
51 // TODO Auto-generated method stub
52 View view = null;
53 if(convertView!=null)
54 {
55 view = convertView;
56 }
57 else
58 {
59 view = LayoutInflater.from(context).inflate(R.layout.layout_item,parent, false);
60 }
61
62 ViewHolder holder = (ViewHolder) view.getTag();
63 if(holder==null)
64 {
65 holder = new ViewHolder();
66 holder.textview = (TextView) view.findViewById(R.id.id_textview);
67 view.setTag(holder);
68 }
69 holder.textview.setText(list.get(position).getName());
70 return view;
71 }
72
73 class ViewHolder
74 {
75 TextView textview;
76 }
77
78 }
MyAdapter.class
4、异步任务获得数据
1 package com.example.listview;
2
3 import java.io.IOException;
4 import java.io.UnsupportedEncodingException;
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import org.json.JSONException;
9
10 import android.os.AsyncTask;
11
12 public class AsyncTaskHome extends AsyncTask<String, Void, List>{
13
14 private MyAdapter myadapter;
15 private List<Home> list ;
16 //将适配器作为参数传进来
17 public AsyncTaskHome(MyAdapter myadapter)
18 {
19 this.myadapter = myadapter;
20 }
21 @Override
22 protected List doInBackground(String... params) {
23 // TODO Auto-generated method stub
24 if(params[0]!=null)
25 {
26 try {
27 String json = new String(HttpUtil.getByteJsonString(params[0]),"utf-8");
28 list = JsonString.getJsonResult(json);
29 } catch (UnsupportedEncodingException e) {
30 // TODO Auto-generated catch block
31 e.printStackTrace();
32 } catch (IOException e) {
33 // TODO Auto-generated catch block
34 e.printStackTrace();
35 } catch (JSONException e) {
36 // TODO Auto-generated catch block
37 e.printStackTrace();
38 }
39 }
40
41 return list;
42 }
43
44 @Override
45 protected void onPostExecute(List result) {
46 // TODO Auto-generated method stub
47 super.onPostExecute(result);
48 //将解析除的数据添加放入到当前适配器中
49 myadapter.addData(result);
50 //刷新适配器
51 myadapter.notifyDataSetChanged();
52
53
54 }
55
56 }
AsyncTaskHome.class
5、主Activity
1 package com.example.listview;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.widget.AbsListView;
6 import android.widget.AbsListView.OnScrollListener;
7 import android.widget.ListView;
8 import android.widget.Toast;
9
10 public class MainActivity extends Activity {
11
12 private ListView listview ;
13 private boolean isEnd; //判断列表是否滑动到底部
14 private int page = 1;//显示第几页数据
15 @Override
16 protected void onCreate(Bundle savedInstanceState) {
17 super.onCreate(savedInstanceState);
18 setContentView(R.layout.activity_main);
19
20 listview = (ListView) findViewById(R.id.listview);
21 //创建一个自定义适配器对象
22 final MyAdapter adapter = new MyAdapter(this);
23 //将该适配器作为listView的数据源
24 listview.setAdapter(adapter);
25 //启动异步任务,先解析第一个页面的数据
26 new AsyncTaskHome(adapter).execute("http://ikft.house.qq.com/index.php?guid=866500021200250&devua=appkft_1080_1920_XiaomiMI4LTE_1.8.3_Android19&order=0&searchtype=normal&devid=866500021200250&appname=QQHouse&mod=appkft&act=searchhouse&channel=71&page=1&rn=20&cityid=1");
27
28 listview.setOnScrollListener(new OnScrollListener() {
29
30 @Override
31 public void onScrollStateChanged(AbsListView view, int scrollState) {
32 // TODO Auto-generated method stub
33 //如果滑動到末尾並且手指離開了界面,則加載新的數據源添加到適配器中
34 if(isEnd && scrollState==OnScrollListener.SCROLL_STATE_IDLE)
35 {
36 Toast.makeText(MainActivity.this, "努力加载中---", 1).show();
37
38 //加载一个新的数据源,包含新的20条数据
39 String path = "http://ikft.house.qq.com/index.php?guid=866500021200250&devua=appkft_1080_1920_XiaomiMI4LTE_1.8.3_Android19&order=0&searchtype=normal&devid=866500021200250&appname=QQHouse&mod=appkft&act=searchhouse&channel=71&page="+(++page)+"&rn=20&cityid=1";
40 //执行异步任务,将当前的自定义适配器传进去,将解析的新的数据添加到当前视频日期中
41 new AsyncTaskHome(adapter).execute(path);
42 }
43 }
44 @Override
45 public void onScroll(AbsListView view, int firstVisibleItem,
46 int visibleItemCount, int totalItemCount) {
47 // TODO Auto-generated method stub
48 //如果已经划出去的列表项和正在显示的列表项==全部列表项,说明列表到达底部
49 isEnd = (firstVisibleItem+visibleItemCount)==totalItemCount;
50 }
51 });
52
53
54 }
55
56
57
58 }
MainActivity.class
效果图: