Android:下拉刷新,分页加载数据(服务端与客户端的的具体实现)

我们在项目开发过程中,最常用的控件就是ListView,常用的场景也就是以列表的方式显示数据,当我们的应用联网的时候,可以下拉刷新获取更多的数据;

当没有更多的数据的时候,会提醒我们没有更多数据。

这里我简单总结了一下分页加载数据,希望大家提出宝贵的意见,或者有什么更好的方法与我一起分享学习:

首先看一下效果图:


服务端代码:

web工程结构图(记得导入需要的jar包):

Android:下拉刷新,分页加载数据(服务端与客户端的的具体实现)_第1张图片

Student.java

package com.xbmu.bean;

import java.io.Serializable;
import java.util.Date;
public class Student implements Serializable {
	private String stuicon;
	private String username;
	private Date birthday;
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(String stuicon, String username, Date birthday) {
		super();
		this.stuicon = stuicon;
		this.username = username;
		this.birthday = birthday;
	}
	public String getStuicon() {
		return stuicon;
	}
	public void setStuIcon(String stuicon) {
		this.stuicon = stuicon;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	@Override
	public String toString() {
		return "Student [stuIcon=" + stuicon + ", username=" + username
				+ ", birthday=" + birthday + "]";
	}
}
StuDataSource.java
package com.xbmu.db;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.xbmu.bean.Student;
/**
 * 模拟数据库,在这里添加100条学生记录
 * @author bitaotao
 *
 */
public class StuDataSource {
	private List<Student> list = new ArrayList<Student>();
	public List<Student> getDataSource() {
		for (int i = 0; i < 100; i++) {
			Student student = new Student("***", "zhangsan"+i,new Date());
			list.add(student);
		}
		return list;
	}
}

DevidePage.java

package com.xbmu.utils;

/**
 * 分页工具
 * 
 * @author bitaotao
 * 
 */
public class DevidePage {
	private int pageSize;// 每页显示的条数
	private int recordCount;// 记录的总条数
	private int currentPage;// 当前页
	private int pageCount;// 总页数

	/**
	 * 
	 * @param pageSize  每页显示的条数
	 * @param recordCount 总记录条数
	 * @param currentPage 当前页数
	 */
	public DevidePage(int pageSize, int recordCount, int currentPage) {
		this.pageSize = pageSize;
		this.recordCount = recordCount;
		this.setCurrentPage(currentPage);
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getRecordCount() {
		return recordCount;
	}

	public void setRecordCount(int recordCount) {
		this.recordCount = recordCount;
	}

	/**
	 * 获得总页数
	 */
	public int getPageCount() {
		pageCount = recordCount / pageSize;
		int mod = recordCount % pageSize;
		if (mod != 0) {
			pageCount++;
		}
		return pageCount == 0 ? 1 : pageCount;
	}

	public void setPageCount(int pageCount) {
		this.pageCount = pageCount;
	}

	public int getCurrentPage() {
		return currentPage;
	}

	/**
	 * 设置定位在当前页
	 */
	private void setCurrentPage(int currentPage) {
		int activePage = currentPage <= 0 ? 1 : currentPage;
		activePage = activePage > getPageCount() ? getPageCount() : activePage;
		this.currentPage = activePage;
	}

	public int getFromIndex() {
		return (currentPage - 1) * pageSize;
	}

	public int getToIndex() {
		return Math.min(recordCount, currentPage * pageSize);
	}

}
JsonDateValueProcessor.java
package com.xbmu.utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
public class JsonDateValueProcessor implements JsonValueProcessor {
	private String pattern = "yyyy-MM-dd";

	public Object processArrayValue(Object value, JsonConfig config) {
		return process(value);
	}

	public Object processObjectValue(String key, Object value, JsonConfig config) {
		return process(value);
	}
	private Object process(Object value){
		if(value instanceof Date){
			SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.UK);
			return sdf.format(value);
		}
		return value == null ? "" : value.toString();
	}

}
StuServlet.java
package com.xbmu.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import com.xbmu.bean.Student;
import com.xbmu.db.StuDataSource;
import com.xbmu.utils.DevidePage;
import com.xbmu.utils.JsonDateValueProcessor;

public class StuServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//解决乱码问题
		response.setContentType("text/html;charset=utf-8");
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");

		StuDataSource dataSource = new StuDataSource();
		/**
		 * 获取StuDataSource类中的数据
		 */
		List<Student> list = dataSource.getDataSource();
		String pageNo = request.getParameter("pageNo");
		int currentPage = 1;// 当前页是第一页
		if (pageNo != null) {
			currentPage = Integer.parseInt(pageNo);
		}
		/**
		 * 分页:每页有25条数据,因为有100条,所以总共有4页。
		 */
		DevidePage pUtil = new DevidePage(25, list.size(), currentPage);
		int start = pUtil.getFromIndex();
		int end = pUtil.getToIndex();
		
		//总页数
		int pageCount = pUtil.getPageCount();
		//分页数据,存储在集合中了
		List<Student> subList = list.subList(start, end);
		
		//json配置对象
		JsonConfig jsonConfig = new JsonConfig();
		//注册json值处理器
		jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor());
		
		//将集合转换成json对象
		Map<String, Object> map = new HashMap<String,Object>();
		map.put("pageCount", pageCount);//将总页数存储到Map集合中
		map.put("sublist", subList);//将分页数据存储到集合中
		
		//将map集合中的数据转换成json格式的字符串
		JSONObject jsonObject = new JSONObject();
		jsonObject = jsonObject.fromObject(map,jsonConfig);
		PrintWriter writer = response.getWriter();
		writer.println(jsonObject);
		writer.flush();
		writer.close();
		
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);

	}
}
启动tomcat,将web程序部署到服务器上。访问地址:http://10.6.159.37:8080/TestServer/stuServlet?pageNo=1

运行结果:

Android:下拉刷新,分页加载数据(服务端与客户端的的具体实现)_第2张图片

客户端代码:

Android:下拉刷新,分页加载数据(服务端与客户端的的具体实现)_第3张图片

MainActivity.java

package com.xbmu;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.xbmu.bean.Student;
import com.xbmu.http.HttpUtil;
import com.xbmu.parser.ParserNetData;
public class MainActivity extends Activity {

	private String BASE_URL = "http://10.6.159.37:8080/TestServer/stuServlet?pageNo=";
	private ListView listView;
	private MyAdapter adapter;
	private boolean is_divPage;// 是否进行分页操作
	private List<Student> oneTotal = new ArrayList<Student>();// 用来存放一页数据
	private List<Student> total = new ArrayList<Student>();// 用来存放获取的所有数据
	private ProgressDialog dialog;// 进度对话框对象
	private static int pageNo = 1;// 设置pageNo的初始化值为1,即默认获取的是第一页的数据。
	private static int pageCount;//总页数,从服务端获取过来
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		listView = (ListView) findViewById(R.id.listView);
		dialog = new ProgressDialog(MainActivity.this);
		dialog.setTitle("警告");
		dialog.setMessage("正在加载信息...");

		adapter = new MyAdapter();
		/**
		 * 用来获取数据...
		 */
		new MyTask().execute(BASE_URL + pageNo);

		listView.setOnScrollListener(new OnScrollListener() {

			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				/**
				 * 当分页操作is_divPage为true时、滑动停止时、且pageNo<=pageCount(这里因为服务端有pageCount页数据)时,加载更多数据。
				 */
				if (is_divPage && scrollState == OnScrollListener.SCROLL_STATE_IDLE && pageNo <= pageCount) {
					Toast.makeText(MainActivity.this, "正在获取更多数据...",
							Toast.LENGTH_SHORT).show();
					new MyTask().execute(BASE_URL + pageNo);
				} else if (pageNo > pageCount) {
					/**
					 * 如果pageNo>pageCount则表示,服务端没有更多的数据可供加载了。
					 */
					Toast.makeText(MainActivity.this, "没有更多数据啦...",
							Toast.LENGTH_SHORT).show();
				}

			}

			/**
			 * 当第一个可见的item(firstVisibleItem)+可见的item的个数(visibleItemCount)=
			 * 所有的item总数的时候, is_divPage变为TRUE,这个时候才会加载数据。
			 */
			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				is_divPage = (firstVisibleItem + visibleItemCount == totalItemCount);

			}
		});

	}
	/**
	 * 覆写activity的销毁方法,在销毁activity之前将初始也pageNo设置为默认值1
	 * 如果没有覆写该方法并没有恢复pageNo的默认值。那么等你退出应用后,重新点击应用图标进去
	 * 会获取不到任何值(因为第一次加载数据的时候,pageNo已经快速增加到pageNo的最大值)
	 * 这里有什么问题或者不同的理解,请各位朋友指出。
	 * */
	@Override
	protected void onDestroy() {
		pageNo = 1;
		super.onDestroy();
	}
	/**
	 * MyTask继承线程池AsyncTask用来网络数据请求、json解析、数据更新等操作。
	 * AsyncTask<Params, Progress, Result>
	 * Params:在执行AsyncTask时需要传入的参数,可用于在后台任务中使用
	 * Progress:后台人物执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位
	 * Result:当人物执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型
	 */
	class MyTask extends AsyncTask<String, Void, String> {
		/**
		 * 数据请求前显示dialog。
		 */
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			dialog.show();
		}

		/**
		 * 在doInBackground方法中,做一些诸如网络请求等耗时操作。
		 */
		@Override
		protected String doInBackground(String... params) {
			return HttpUtil.RequestData(BASE_URL + pageNo);
		}

		/**
		 * 在该方法中,主要进行一些数据的处理,更新。
		 */
		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);
			if (result != null) {
				// 如果获取的result数据不为空,那么对其进行JSON解析。并显示在手机屏幕上。
				oneTotal.clear();
				List<Student> list = ParserNetData.parseFromJson(oneTotal,result);
				pageCount = (Integer) ParserNetData.getPageCount(result);
				total.addAll(list);
				adapter.bindData(total);
				/**
				 * 当pageNo等于1的时候才会setAdapter,以后不会再设置,直接notifyDataSetChanged,
				 * 进行数据更新 ,这样可避免每次加载更多数据的时候,都会重新回到第一页。
				 */
				if (pageNo == 1) {
					listView.setAdapter(adapter);
				}
				adapter.notifyDataSetChanged();
				pageNo++;
				System.out.println("pageNo="+pageNo);
			} else if (result == null) {
				Toast.makeText(MainActivity.this, "请求数据失败...",
						Toast.LENGTH_LONG).show();
			}
			dialog.dismiss();
		}
	}

	/**
	 * ListView的适配器
	 */
	class MyAdapter extends BaseAdapter {
		List<Student> list;

		/**
		 * bindData用来传递数据给适配器。
		 * 
		 * @param list
		 */
		public void bindData(List<Student> list) {
			this.list = list;
		}

		@Override
		public int getCount() {
			return list.size();
		}

		@Override
		public Object getItem(int position) {
			return list.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View view = View.inflate(MainActivity.this, R.layout.list_item,
					null);
			ImageView iv_icon = (ImageView) view.findViewById(R.id.iv_icon);
			TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
			TextView tv_date = (TextView) view.findViewById(R.id.tv_date);
			iv_icon.setBackgroundResource(R.drawable.notice);
			tv_name.setText(list.get(position).getUsername());
			
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			Date birthdayDate = list.get(position).getBirthday();
			String birthday = dateFormat.format(birthdayDate);
			tv_date.setText(birthday);
			return view;
		}
	}
}

Student.java和服务端的bean一样,这里不再写了。

HttpUtil.java

package com.xbmu.http;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
public class HttpUtil {
	/**
	 * 分页请求网络数据
	 * @param pageNo 请求的页码
	 * @return 返回json格式的数据
	 */
	public static String RequestData(String netUrl) {
		HttpGet get = new HttpGet(netUrl);
		HttpClient client = new DefaultHttpClient();
		StringBuilder builder = null;
		try {
			HttpResponse response = client.execute(get);
			if (response.getStatusLine().getStatusCode() == 200) {
				InputStream inputStream = response.getEntity().getContent();
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(inputStream));
				builder = new StringBuilder();
				String s = null;
				for (s = reader.readLine(); s != null; s = reader.readLine()) {
					builder.append(s);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return builder.toString();
	}
}
ParserNetData.java
package com.xbmu.parser;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.xbmu.bean.Student;
public class ParserNetData {
	/**
	 * 解析json字符串
	 * @param oneTotal 该集合用来存放一页数据
	 * @param result 请求网络,服务器返回的字符串(json格式)
	 * @return
	 */
	public static List<Student> parseFromJson(List<Student> oneTotal,String result) {
		JSONArray array = null;
		JSONObject jsonObject = null;
		try {
			jsonObject = new JSONObject(result);
			String sublist = jsonObject.getString("sublist");
			array = new JSONArray(sublist);
			for (int i = 0; i < array.length(); i++) {
				JSONObject obj = array.getJSONObject(i);
				Student stuInfo = new Student();
				stuInfo.setStuIcon(obj.getString("stuicon"));
				stuInfo.setUsername(obj.getString("username"));
				String dateStr = obj.getString("birthday");
				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
				Date birthday = dateFormat.parse(dateStr);
				stuInfo.setBirthday(birthday);
				oneTotal.add(stuInfo);
			}
			return oneTotal;
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * 获得总页数
	 * @param result json字符串
	 * @return 返回json封装的总页数
	 */
	public static Object getPageCount(String result){
		try {
			JSONObject jsonObject = new JSONObject(result);
			Object pageCount = jsonObject.get("pageCount");
			System.out.println("总页数"+pageCount);
			return pageCount;
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
}

客户端与服务端所有源码下载地址:

http://download.csdn.net/detail/btt2013/9323905





你可能感兴趣的:(ListView下拉刷新,分页加载数据)