zoukankan      html  css  js  c++  java
  • ListView动态加载数据分页(使用Handler+线程和AsyncTask两种方法)

         在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、主要代码

      1 public class HandlerDemo extends Activity implements OnScrollListener {
      2 
      3     private ListView mListView;
      4     LinearLayout loadingLayout;
      5     private Thread mThread;
      6     private ListViewAdapter adapter;
      7 
      8     private int startIndex = 1;// 从第1条开始
      9     private int size = 10;// 每次下载十条数据
     10     private List<News> newsList;
     11     List<Map<String, String>> data ;
     12 
     13     /*
     14      * 设置布局显示属性
     15      */
     16     private LayoutParams mLayoutParams = new LayoutParams(
     17             LinearLayout.LayoutParams.WRAP_CONTENT,
     18             LinearLayout.LayoutParams.WRAP_CONTENT);
     19 
     20     private LayoutParams ffLayoutParams = new LayoutParams(
     21             LinearLayout.LayoutParams.FILL_PARENT,
     22             LinearLayout.LayoutParams.FILL_PARENT);
     23 
     24     private ProgressBar progressBar;
     25 
     26     @Override
     27     protected void onCreate(Bundle savedInstanceState) {
     28         // TODO Auto-generated method stub
     29         super.onCreate(savedInstanceState);
     30         setContentView(R.layout.news_main);
     31         data=new ArrayList<Map<String, String>>();
     32         addView();
     33     }
     34 
     35     private void addView() {
     36         if (startIndex == 1) {
     37             newsList = new ArrayList<News>();
     38             newsList = getNewsList();
     39         }
     40         getdata(newsList);
     41         LinearLayout layout = new LinearLayout(this);
     42         layout.setOrientation(LinearLayout.HORIZONTAL);
     43         progressBar = new ProgressBar(this);
     44         layout.addView(progressBar, mLayoutParams);
     45         TextView textView = new TextView(this);
     46         textView.setText("加载中...");
     47         textView.setGravity(Gravity.CENTER_VERTICAL);
     48         layout.addView(textView, ffLayoutParams);
     49         layout.setGravity(Gravity.CENTER);
     50         loadingLayout = new LinearLayout(this);
     51         loadingLayout.addView(layout, mLayoutParams);
     52         loadingLayout.setGravity(Gravity.CENTER);
     53 
     54         // 得到一个ListView用来显示条目
     55         mListView = (ListView) findViewById(R.id.listView);
     56         mListView.addFooterView(loadingLayout);
     57         adapter = new ListViewAdapter();
     58         mListView.setAdapter(adapter);
     59         mListView.setOnScrollListener(this);
     60         mListView.setTextFilterEnabled(true);
     61     }
     62 
     63     @Override
     64     public void onScroll(AbsListView view, int firstVisibleItem,
     65             int visibleItemCount, int totalItemCount) {
     66         // TODO Auto-generated method stub
     67         if (firstVisibleItem + visibleItemCount == totalItemCount) {
     68             if (mThread == null || !mThread.isAlive()) {
     69                 mThread = new Thread() {
     70 
     71                     @Override
     72                     public void run() {
     73                         newsList = new ArrayList<News>();
     74                         newsList = getNewsList();
     75                         getdata(newsList);
     76                         Message msg = new Message();
     77                         msg.what = 1;
     78                         handler.sendMessage(msg);
     79                     }
     80                 };
     81                 mThread.run();
     82             }
     83         }
     84     }
     85     
     86     Handler handler = new Handler() {
     87 
     88         @Override
     89         public void handleMessage(Message msg) {
     90             // TODO Auto-generated method stub
     91             if (msg.what == 1) {
     92                 startIndex = startIndex + size;
     93                 Log.v("startindex", startIndex + "");
     94                 mListView.removeFooterView(loadingLayout);
     95                 mThread.stop();
     96                 adapter.count += size;
     97                 adapter.notifyDataSetChanged();
     98                 return;
     99             }
    100         }
    101     };
    102 
    103     class ListViewAdapter extends BaseAdapter {
    104         int count = 10;
    105 
    106         @Override
    107         public int getCount() {
    108             // TODO Auto-generated method stub
    109             return count;
    110         }
    111 
    112         @Override
    113         public Object getItem(int position) {
    114             // TODO Auto-generated method stub
    115             return position;
    116         }
    117 
    118         @Override
    119         public long getItemId(int position) {
    120             // TODO Auto-generated method stub
    121             return position;
    122         }
    123         
    124         @Override
    125         public View getView(int position, View convertView, ViewGroup parent) {
    126             // TODO Auto-generated method stub
    127             convertView = LayoutInflater.from(getApplicationContext()).inflate(
    128                     R.layout.news_item, null);
    129             TextView textView = (TextView) convertView
    130                     .findViewById(R.id.textNewsTitle);
    131             textView.setText((data.get(position)).get("title"));
    132             return convertView;
    133         }
    134     }
    135 
    136     @Override
    137     public void onScrollStateChanged(AbsListView view, int scrollState) {
    138         // TODO Auto-generated method stub
    139 
    140     }
    141 
    142     private List<Map<String, String>> getdata(List<News> list) {
    143 
    144         if (list == null)
    145             return null;
    146         for (News news : list) {
    147             Map<String, String> map = new HashMap<String, String>();
    148             map.put("title", news.getTitle());
    149             data.add(map);
    150         }
    151         return data;
    152     }
    153 
    154     /*
    155      * 获取网络数据 注:我是访问本机的一个新闻服务,使用asp.net技术来实现的
    156      * 这个是项目是一个基于android的资讯播报软件
    157      */
    158     private List<News> getNewsList() {
    159         String path = "http://10.0.2.2/getNewsList.aspx";
    160         String xmlStr = "<?xml version='1.0' encoding='utf-8'?><source><categoryIds>1,3,7</categoryIds><startIndex>"
    161                 + startIndex
    162                 + "</startIndex><detail>2</detail><count>"
    163                 + size
    164                 + "</count></source>";
    165         NewsConnector newsConnector = new NewsConnector();
    166         List<News> list = new ArrayList<News>();
    167         list = newsConnector.getNewsList(path, xmlStr);
    168         return list;
    169     }
    170 }

    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、主要代码

     1 @Override
     2     public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
     3         // TODO Auto-generated method stub
     4         if(arg1+arg2==arg3)
     5         {
     6             if(!isloading)
     7             {
     8                 new myAsyncTask().execute(null);
     9             }
    10             else
    11             {
    12                 mListView.removeFooterView(loadingLayout);
    13             }
    14         }
    15     }
    16 
    17     @Override
    18     public void onScrollStateChanged(AbsListView arg0, int arg1) {
    19         // TODO Auto-generated method stub
    20         
    21     }
    22     
    23     private class myAsyncTask extends AsyncTask<Void, Void, Void>
    24     {
    25 
    26         @Override
    27         protected Void doInBackground(Void... params) {
    28             // TODO Auto-generated method stub
    29             
    30             newsList = new ArrayList<News>();
    31             newsList = getNewsList();
    32             getdata(newsList);
    33             return null;
    34             
    35         }
    36 
    37         @Override
    38         protected void onPostExecute(Void result) {
    39             // TODO Auto-generated method stub
    40             super.onPostExecute(result);
    41             adapter.count+=size;
    42             adapter.notifyDataSetChanged();
    43             startIndex+=size;
    44             isloading=false;
    45         }
    46 
    47         @Override
    48         protected void onPreExecute() {
    49             // TODO Auto-generated method stub
    50             super.onPreExecute();
    51             isloading=true;
    52         }
    53         
    54     }

    注:以上仅是和使用Handler+线程方法不同的代码,建议下载源码,了解详细代码

    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变得比较复杂。

     
    附件上截图

      

  • 相关阅读:
    array_map()与array_shift()搭配使用 PK array_column()函数
    Educational Codeforces Round 8 D. Magic Numbers
    hdu 1171 Big Event in HDU
    hdu 2844 poj 1742 Coins
    hdu 3591 The trouble of Xiaoqian
    hdu 2079 选课时间
    hdu 2191 珍惜现在,感恩生活 多重背包入门题
    hdu 5429 Geometric Progression 高精度浮点数(java版本)
    【BZOJ】1002: [FJOI2007]轮状病毒 递推+高精度
    hdu::1002 A + B Problem II
  • 原文地址:https://www.cnblogs.com/JerryWang1991/p/2388312.html
Copyright © 2011-2022 走看看