Android实现listview动态加载数据分页的两种方法
在android开发中,经常需要使用数据分页,比如要实现一个新闻列表的显示,或者博文列表的显示,不可能第一次加载就展示出全部,这就需要使用分页的方法来加载数据,在android中Handler经常用来在耗时的工作中,它接收子线程发送的数据,并使用数据配合更新UI,AsyncTask是在一个线程中执行耗时操作然后把结果传给UI线程,不需要你亲自去管理线程和句柄。
一、使用Handler+线程方法
1、基础知识
Handler在android系统中,主要负责发送和接收消息,它的用途主要有以下两种:
(1)按照计划来处理一个消息(sendMessage(Message)方法)或者执行某个runnable实例(post(Runnable)方法)
(2)把其他的线程对象放入消息队列中,避免线程冲突。
消息的发送通过post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int),sendMessage(Message), sendMessageAtTime(Message, long)和 sendMessageDelayed(Message, long) 方法完成。对于postXXX方法通过Runnable对象给消息队列,并在消息队列到达后被调用。对于sendMessageXXX方法,则传递一个包含message对象,该对象可以被Handler类的handlerMessage(Message)方法处理。
2、主要代码
public class HandlerDemo extends Activity implements OnScrollListener {
private ListView mListView;
LinearLayout loadingLayout;
private Thread mThread;
private ListViewAdapter adapter;
private int startIndex = 1;// 从第1条开始
private int size = 10;// 每次下载十条数据
private List<News> newsList;
List<Map<String, String>> data ;
private LayoutParams mLayoutParams = new LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
private LayoutParams ffLayoutParams = new LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.news_main);
data=new ArrayList<Map<String, String>>();
addView();
}
private void addView() {
if (startIndex == 1) {
newsList = new ArrayList<News>();
newsList = getNewsList();
}
getdata(newsList);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
progressBar = new ProgressBar(this);
layout.addView(progressBar, mLayoutParams);
TextView textView = new TextView(this);
textView.setText("加载中...");
textView.setGravity(Gravity.CENTER_VERTICAL);
layout.addView(textView, ffLayoutParams);
layout.setGravity(Gravity.CENTER);
loadingLayout = new LinearLayout(this);
loadingLayout.addView(layout, mLayoutParams);
loadingLayout.setGravity(Gravity.CENTER);
// 得到一个ListView用来显示条目
mListView = (ListView) findViewById(R.id.listView);
mListView.addFooterView(loadingLayout);
adapter = new ListViewAdapter();
mListView.setAdapter(adapter);
mListView.setOnScrollListener(this);
mListView.setTextFilterEnabled(true);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
if (firstVisibleItem + visibleItemCount == totalItemCount) {
if (mThread == null || !mThread.isAlive()) {
mThread = new Thread() {
@Override
public void run() {
newsList = new ArrayList<News>();
newsList = getNewsList();
getdata(newsList);
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
};
mThread.run();
}
}
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
if (msg.what == 1) {
startIndex = startIndex + size;
Log.v("startindex", startIndex + "");
mListView.removeFooterView(loadingLayout);
mThread.stop();
adapter.count += size;
adapter.notifyDataSetChanged();
return;
}
}
};
class ListViewAdapter extends BaseAdapter {
int count = 10;
@Override
public int getCount() {
// TODO Auto-generated method stub
return count;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return 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
convertView = LayoutInflater.from(getApplicationContext()).inflate(
R.layout.news_item, null);
TextView textView = (TextView) convertView
.findViewById(R.id.textNewsTitle);
textView.setText((data.get(position)).get("title"));
return convertView;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
private List<Map<String, String>> getdata(List<News> list) {
if (list == null)
return null;
for (News news : list) {
Map<String, String> map = new HashMap<String, String>();
map.put("title", news.getTitle());
data.add(map);
}
return data;
}
private List<News> getNewsList() {
String path = "http://10.0.2.2/getNewsList.aspx";
String xmlStr = "<?xml version='1.0' encoding='utf-8'?><source><categoryIds>1,3,7</categoryIds><startIndex>"
+ startIndex
+ "</startIndex><detail>2</detail><count>"
+ size
+ "</count></source>";
NewsConnector newsConnector = new NewsConnector();
List<News> list = new ArrayList<News>();
list = newsConnector.getNewsList(path, xmlStr);
return list;
}
}
3、小结
ListView使用Handler+线程方式来动态加载数据的步骤如下:
1.先初始化页面(如:加载第一页数据)
2.在接收某个事件的消息之后(以上代码是onScroll事件),启动线程(线程完成下载数据,并发送消息给handler)
3.handler接收到消息后更新界面,显示数据。
二、使用AsyncTask方法
1、基础知识
AsyncTask也是android提供的一个为了不能阻塞主线程的一个类,AsyncTask定义了三种泛型类型Params、Progress和Result,Params启动任务执行输入参数,比如http请求的url和参数,Progress后台执行任务的百分比,后台执行最终返回的结果。
AsyncTask的执行分为四个步骤,每一步都对应都对应一个回调方法,开发者需要实现一个或者几个方法,在任务的执行过程中,这些方法会自动调用。
onPreExecute(),在执行后台耗时操作前被调用,可以在执行此方法中做一些ui操作,比如显示一个进度条等
doInBackground(Params...),这个方法在执行onPreExecute()后执行,这个方法完成耗时工作,比如下载等。
onProgressUpdate(Progress...),UI线程通过此方法获取任务的完成的情况,比如完成的任务的百分比。
onPostExecute(Result),这个方法在耗时工作完成后被调用。UI线程调用此方法获取结果。
注意:在使用AsyncTask类,有几条准则需要遵守
(1)、Task的实例必须在UI线程中创建
(2)、execute方法必须在UI线程中调用
(3)、不要手动调用以上四个方法
(4)、这个任务只执行一次(如果执行第二次将会抛出异常)
2、主要代码
@Override
public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
if(arg1+arg2==arg3)
{
if(!isloading)
{
new myAsyncTask().execute(null);
}
else
{
mListView.removeFooterView(loadingLayout);
}
}
}
@Override
public void onScrollStateChanged(AbsListView arg0, int arg1) {
// TODO Auto-generated method stub
}
private class myAsyncTask extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
newsList = new ArrayList<News>();
newsList = getNewsList();
getdata(newsList);
return null;
}
@Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
adapter.count+=size;
adapter.notifyDataSetChanged();
startIndex+=size;
isloading=false;
}
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
isloading=true;
}
}
注:以上仅是和使用Handler+线程方法不同的代码,建议下载源码:http://xiazai.jb51.net/201606/yuanma/NewsList(jb51.net).rar,了解详细代码
3、小结
ListView使用AsyncTask方法动态加载数据的方法如下:
1.和handler一样初始化页面(如:加载第一页)
2.在接收某个事件的消息之后(以上代码是onScroll事件),创建一个新的异步任务,并开始执行
3.耗时工作完成后,开始更新UI
三、总结
使用Handler+线程和使用AsyncTask方法进行ListView动态加载的比较
Handler+线程方式:
在使用Handler方式时,它涉及Handler、Thread、Message、Looper四个对象,在执行的流程如下:主线程启动一个Thread,这个Thread执行耗时操作,耗时操作完成后,生成一个Message,Looper读取Message并传递给Hander,Handler接收Message并更新响应的UI。因为Looper在一个message处理完,才会读下一条,如果发生多个Message就会形成一个消息队列,所以它对多个后台操作比较清晰,明朗。但对于单个message来讲显得代码比较多,过于复杂。
AsyncTask方式:
AsyncTask继承自Object,是android提供的轻量级的异步类。并提供了一个方法来获取任务的执行进度(可以根据它来更新UI),最后会把结果返回在主线程。这个方式的比较简单,而且可以清楚的看到耗时任务执行的进度。但是对于多个异步操作同时进行,并更新UI变得比较复杂。
附件上截图
参考文章:Android listview动态加载列表项实现代码
您可能感兴趣的文章:android ListView内数据的动态添加与删除实例代码android动态布局之动态加入TextView和ListView的方法Android实现Listview异步加载网络图片并动态更新的方法Android编程实现动态更新ListView的方法Android开发之利用ListView动态刷新某个ItemAndroid listview动态加载列表项实现代码Android实现ListView数据动态加载的方法Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)Android ListView中动态显示和隐藏Header&Footer的方法Android ListView中headerview的动态显示和隐藏的实现方法Android开发中Listview动态加载数据的方法示例
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341