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

     
    附件上截图

      

  • 相关阅读:
    hibernate事务管理
    oracle的中文排序问题
    hibernate一级缓存
    Hibernate的实体规则、主键生成策略、对象状态
    【SVN】命令行忽略不必要的文件和文件夹
    【SVN】SVN的trunk、branches、tag的使用以及分支的概念
    hibernate介绍及环境搭建
    敏捷实践:比每日会议更疯狂的半日会议!
    Android开发之有效获取状态栏(StatusBar)高度
    jquery判断输入文字个数的统计代码
  • 原文地址:https://www.cnblogs.com/JerryWang1991/p/2388312.html
Copyright © 2011-2022 走看看