安卓开发_浅谈ListView之分页列表

时间:2022-02-07 06:32:35

前言:

在开发的过程中,有时候我们需要从网络解析一些数据,比如最近的一些新闻,我们需要把这些数据用ListView显示出来。

因为是解析一个网络数据源,这样将会一下子将所有的数据解析出来,当数据源数据过大时,就可能会造成解析时间过长,占用内存过大等问题。

这时候想到用分页列表来显示这些数据,即每次只显示一个屏幕所能容纳条数的列表项数据,当用户手指向下拉动的时候,才再加载一个屏幕所能容纳的条数的数据,这样就解决了上述问题。

---------------------------------------------------------------------------------------------------------------------------------

思路:

先来看一个数据源地址,内容为某一个城市待出售房屋信息

 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格式

 {
"retcode": ,
"retmsg": "成功",
"total": "",
"page": ,
"rn": ,
"data": [
{
"fid": "",
"fcover": "http://p0.qpic.cn/estate/0/cbcef0b36d585650ec602ebe0ca56a18.jpg/180",
"fname": "鸿坤·理想湾",
"faddress": "涿州东高铁新城涿州东站西侧300米",
"fregion": "大北京",
"fpricedisplaystr": "7200元/平米",
"faroundhighprice": ,
"faroundlowprice": ,
"groupbuynum": ,
"lng": "116.052084096376",
"lat": "39.4636526249295",
"fsellstatus": "",
"istencentdiscount": ,
"bookmark": [
{
"tag": "看房团",
"type":
},
{
"tag": "低总价",
"type":
},
{
"tag": "品牌开发商",
"type":
}
],
"price_pre": "均价",
"price_value": "",
"price_unit": "元/平米",
"panoid": "",
"heading": "",
"pitch": "",
"has_agent": ,
"hui":
},

也就是说,当我们解析这个网址的数据时,会有20条数据,当把网址红色部分page=1 --->page=2 时,又将显示20条数据

怎么实现分页列表一次显示20条数据呢?

从数据源网址可以看出一个我们只要把page依次加一,便可以依次加载对应网址数据源了

也就是说,只要把每次加载的数据添加到适配器中,便可以实现分页列表每页每次加载固定个数个数据条

------------------------------------------------------------------------------------------------------------------------------------------------------------

代码:

1、解析房屋信息,我们这里先只获得房屋名字信息放到ListView中

先建一个房屋实体类

 package com.example.listview;

 public class Home {
private String name; public Home() {
super();
// TODO Auto-generated constructor stub
} public Home(String name) {
super();
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return name;
} }

Home.class

2、工具类(http获取数据,json数据解析)

 package com.example.listview;

 import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; public class HttpUtil {
//将指定路径上的数据转换为字节数组形式返回
public static byte[] getByteJsonString(String path) throws IOException
{
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET"); //Get的连接方式
conn.setConnectTimeout();
conn.setDoInput(true);
if(conn.getResponseCode()==)// 响应码等于200表示连接成功
{
InputStream in = conn.getInputStream();
return getByteString(in);
}
return null; } public static byte[] getByteString(InputStream in) throws IOException
{
//内存流获取数据
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len = ;
byte[] b = new byte[];
while((len = in.read(b))!=-)
{
//注意不要写成out.write(b); 否则若字节数据长度大于实际数据长度,后面部分乱码,导致后面json解析出错
out.write(b,,len);
} return out.toByteArray();
} }

HttpUtil.class

 package com.example.listview;

 import java.util.ArrayList;
import java.util.List; import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject; public class JsonString {
public static List getJsonResult(String json) throws JSONException
{
//JSON解析 ,解析某一城市下所有房屋的名字
List<Home> list = new ArrayList<Home>();
JSONObject obj = new JSONObject(json);
JSONArray arr = obj.getJSONArray("data");
Home home = null;
for(int i=;i<arr.length();i++)
{ JSONObject data = arr.getJSONObject(i);
home = new Home(); String fname =data.getString("fname");
home.setName(fname);
list.add(home);
}
return list; }
}

JsonString.class解析JSON数据

3、ListView的自定义适配器类

 package com.example.listview;

 import java.util.ArrayList;
import java.util.List; import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView; public class MyAdapter extends BaseAdapter{ private Context context;
private List<Home> list; public MyAdapter(Context context)
{
this.context = context;
list = new ArrayList<Home>();
}
//关键点!
//将底部下拉刷新出来的数据(新解析出来的固定条数数据)添加到当前适配器中
public void addData(List lists){
list.addAll(lists);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
int count = ;
if(list!=null)
return list.size();
return count;
} @Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = null;
if(convertView!=null)
{
view = convertView;
}
else
{
view = LayoutInflater.from(context).inflate(R.layout.layout_item,parent, false);
} ViewHolder holder = (ViewHolder) view.getTag();
if(holder==null)
{
holder = new ViewHolder();
holder.textview = (TextView) view.findViewById(R.id.id_textview);
view.setTag(holder);
}
holder.textview.setText(list.get(position).getName());
return view;
} class ViewHolder
{
TextView textview;
} }

MyAdapter.class

4、异步任务获得数据

 package com.example.listview;

 import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List; import org.json.JSONException; import android.os.AsyncTask; public class AsyncTaskHome extends AsyncTask<String, Void, List>{ private MyAdapter myadapter;
private List<Home> list ;
//将适配器作为参数传进来
public AsyncTaskHome(MyAdapter myadapter)
{
this.myadapter = myadapter;
}
@Override
protected List doInBackground(String... params) {
// TODO Auto-generated method stub
if(params[]!=null)
{
try {
String json = new String(HttpUtil.getByteJsonString(params[]),"utf-8");
list = JsonString.getJsonResult(json);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} return list;
} @Override
protected void onPostExecute(List result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//将解析除的数据添加放入到当前适配器中
myadapter.addData(result);
//刷新适配器
myadapter.notifyDataSetChanged(); } }

AsyncTaskHome.class

5、主Activity

 package com.example.listview;

 import android.app.Activity;
import android.os.Bundle;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.Toast; public class MainActivity extends Activity { private ListView listview ;
private boolean isEnd; //判断列表是否滑动到底部
private int page = ;//显示第几页数据
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); listview = (ListView) findViewById(R.id.listview);
//创建一个自定义适配器对象
final MyAdapter adapter = new MyAdapter(this);
//将该适配器作为listView的数据源
listview.setAdapter(adapter);
//启动异步任务,先解析第一个页面的数据
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"); listview.setOnScrollListener(new OnScrollListener() { @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
//如果滑動到末尾並且手指離開了界面,則加載新的數據源添加到適配器中
if(isEnd && scrollState==OnScrollListener.SCROLL_STATE_IDLE)
{
Toast.makeText(MainActivity.this, "努力加载中---", ).show(); //加载一个新的数据源,包含新的20条数据
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";
//执行异步任务,将当前的自定义适配器传进去,将解析的新的数据添加到当前视频日期中
new AsyncTaskHome(adapter).execute(path);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
//如果已经划出去的列表项和正在显示的列表项==全部列表项,说明列表到达底部
isEnd = (firstVisibleItem+visibleItemCount)==totalItemCount;
}
}); } }

MainActivity.class

效果图:

安卓开发_浅谈ListView之分页列表