• Android 之异步任务(AsyncTask,Handler,Message,looper)


    AsyncTask: 3个类型(Params,Progress和Result),4个步骤(onPreExecute(),doInBackground(Params…),onProgressUpdate(Progress…), onPostExecute(Result) )

    Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。
    首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。
     
    Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。

    AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。

     AsyncTask定义了三种泛型类型 Params,Progress和Result。可以为Void表示无类型

    • Params 启动任务执行的输入参数,比如HTTP请求的URL。
    • Progress 后台任务执行的百分比。
    • Result 后台执行任务最终返回的结果,比如String。

    使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

    • doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
    • onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

    有必要的话你还得重写以下这三个方法,但不是必须的:

    • onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
    • onPreExecute()        这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
    • onCancelled()             用户调用取消时,要做的操作

    使用AsyncTask类,以下是几条必须遵守的准则:

    • Task的实例必须在UI thread中创建;
    • execute方法必须在UI thread中调用;
    • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
    • 该task只能被执行一次,否则多次调用时将会出现异常;

    一个最简单的异步任务例子:从网上下载一副图片

      1 package com.example.android_03asynctask;
      2 
      3 import org.apache.http.HttpEntity;
      4 import org.apache.http.HttpResponse;
      5 import org.apache.http.client.HttpClient;
      6 import org.apache.http.client.methods.HttpGet;
      7 import org.apache.http.impl.client.DefaultHttpClient;
      8 import org.apache.http.util.EntityUtils;
      9 
     10 import android.app.Activity;
     11 import android.app.ProgressDialog;
     12 import android.graphics.Bitmap;
     13 import android.graphics.BitmapFactory;
     14 import android.os.AsyncTask;
     15 import android.os.Bundle;
     16 import android.view.Menu;
     17 import android.view.MenuItem;
     18 import android.view.View;
     19 import android.widget.Button;
     20 import android.widget.ImageView;
     21 
     22 public class MainActivity extends Activity {
     23 
     24     private Button button;
     25     private ImageView imageView;
     26     private String image_Path="http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg";
     27     private ProgressDialog progressDialog;
     28     @Override
     29     protected void onCreate(Bundle savedInstanceState) {
     30         super.onCreate(savedInstanceState);
     31         setContentView(R.layout.activity_main);
     32         button=(Button)this.findViewById(R.id.button1);
     33         imageView=(ImageView)this.findViewById(R.id.imageView1);
     34         imageView=(ImageView)this.findViewById(R.id.imageView1);
     35         progressDialog=new ProgressDialog(this);
     36         progressDialog.setTitle("提示信息");
     37         progressDialog.setMessage("正在下载....");
     38         button.setOnClickListener(new View.OnClickListener() {
     39             
     40             @Override
     41             public void onClick(View v) {
     42                 // TODO Auto-generated method stub
     43                 //在UI主线程中不能直接访问网络,所以下面的写法是不正确的,必须使用异步任务
     44             /*    HttpClient httpClient=new DefaultHttpClient();
     45                 HttpGet httpGet=new HttpGet(image_Path);
     46                 try {
     47                     httpClient.execute(httpGet);
     48                 } catch (Exception e) {
     49                     // TODO: handle exception
     50                     e.printStackTrace();
     51                 }*/
     52                 
     53                 //执行异步任务操作
     54                 new myTask().execute(image_Path);
     55             }
     56         });
     57     }
     58  
     59     /**
     60      * 1.声明异步类继承AsyncTask,含有三个参数
     61      *     params 要执行的任务,一般为网络路径url
     62      *     progress 进度的刻度 一般为 Void,表示没有类型
     63      *     result任务执行的返回值
     64      * 2.
     65      * @author Administrator
     66      *
     67      */
     68 public class myTask extends AsyncTask<String, Void, Bitmap>{
     69 
     70     //任务执行之前的操作
     71     @Override
     72         protected void onPreExecute() {
     73             // TODO Auto-generated method stub
     74             super.onPreExecute();
     75             progressDialog.show();
     76         }
     77  
     78     //主要完成耗时操作
     79     @Override
     80     protected Bitmap doInBackground(String... params) {
     81         // TODO Auto-generated method stub
     82         //使用网络连接类HttpClient完成对网络数据的提取
     83         HttpClient httpClient=new DefaultHttpClient();
     84         HttpGet httpGet=new HttpGet(params[0]);//从可变参数取得第一个参数
     85         Bitmap bitmap=null;
     86         try {
     87             HttpResponse httpResponse=httpClient.execute(httpGet);
     88             if(httpResponse.getStatusLine().getStatusCode()==200){
     89                 HttpEntity httpEntity=httpResponse.getEntity();//获取结果实体
     90                 byte[] data=EntityUtils.toByteArray(httpEntity);//将结果实体转换成字节数组
     91                 bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);//将数据转换成bitmap对象
     92                 
     93             }
     94             
     95         } catch (Exception e) {
     96             // TODO: handle exception
     97             e.printStackTrace();
     98         }
     99         return bitmap;
    100     }
    101     
    102     //主要是更新UI操作
    103     @Override
    104     protected void onPostExecute(Bitmap result) {
    105         // TODO Auto-generated method stub
    106         super.onPostExecute(result);
    107         imageView.setImageBitmap(result);
    108         progressDialog.dismiss();
    109     }
    110 }
    111     @Override
    112     public boolean onCreateOptionsMenu(Menu menu) {
    113         // Inflate the menu; this adds items to the action bar if it is present.
    114         getMenuInflater().inflate(R.menu.main, menu);
    115         return true;
    116     }
    117 
    118     @Override
    119     public boolean onOptionsItemSelected(MenuItem item) {
    120         // Handle action bar item clicks here. The action bar will
    121         // automatically handle clicks on the Home/Up button, so long
    122         // as you specify a parent activity in AndroidManifest.xml.
    123         int id = item.getItemId();
    124         if (id == R.id.action_settings) {
    125             return true;
    126         }
    127         return super.onOptionsItemSelected(item);
    128     }
    129 }
    View Code

    上面的实例中并未显示进度条上的刻度,对上个例子完善如下:

      1 package com.example.android_03asynctsk2;
      2 
      3 import java.io.ByteArrayOutputStream;
      4 import java.io.IOException;
      5 import java.io.InputStream;
      6 import java.io.OutputStream;
      7 
      8 import org.apache.http.HttpEntity;
      9 import org.apache.http.HttpResponse;
     10 import org.apache.http.client.HttpClient;
     11 import org.apache.http.client.methods.HttpGet;
     12 import org.apache.http.impl.client.DefaultHttpClient;
     13 import org.apache.http.util.EntityUtils;
     14 
     15 import android.app.Activity;
     16 import android.app.ProgressDialog;
     17 import android.graphics.Bitmap;
     18 import android.graphics.BitmapFactory;
     19 import android.os.AsyncTask;
     20 import android.os.Bundle;
     21 import android.view.Menu;
     22 import android.view.MenuItem;
     23 import android.view.View;
     24 import android.widget.Button;
     25 import android.widget.ImageView;
     26 
     27 public class MainActivity extends Activity {
     28     private Button button;
     29     private ImageView imageView;
     30     private String image_Path = "http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg";
     31     private ProgressDialog progressDialog;
     32 
     33     @Override
     34     protected void onCreate(Bundle savedInstanceState) {
     35         super.onCreate(savedInstanceState);
     36         setContentView(R.layout.activity_main);
     37         button = (Button) this.findViewById(R.id.button1);
     38         imageView = (ImageView) this.findViewById(R.id.imageView1);
     39         progressDialog = new ProgressDialog(this);
     40         progressDialog.setTitle("提示");
     41         progressDialog.setMessage("正在下载....");
     42         progressDialog.setCancelable(false);// 使屏幕失去焦点,直至下载完成才恢复焦点
     43         progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 设置进度条为横向的
     44         button.setOnClickListener(new View.OnClickListener() {
     45 
     46             @Override
     47             public void onClick(View v) {
     48                 // TODO Auto-generated method stub
     49                 new myTask().execute(image_Path);
     50 
     51             }
     52         });
     53     }
     54 
     55     public class myTask extends AsyncTask<String, Integer, Bitmap> {
     56 
     57         @Override
     58         protected void onPreExecute() {
     59             // TODO Auto-generated method stub
     60             super.onPreExecute();
     61             progressDialog.show();
     62         }
     63 
     64         @Override
     65         protected Bitmap doInBackground(String... params) {
     66             // TODO Auto-generated method stub
     67             HttpClient httpClient = new DefaultHttpClient();
     68             HttpGet httpGet = new HttpGet(params[0]);// 从可变参数取得第一个参数
     69             Bitmap bitmap = null;
     70             ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
     71             InputStream inputStream=null;
     72             try {
     73                 HttpResponse httpResponse = httpClient.execute(httpGet);
     74                 if (httpResponse.getStatusLine().getStatusCode() == 200) {
     75                     inputStream=httpResponse.getEntity().getContent();//得到输入流
     76                     long file_Length=httpResponse.getEntity().getContentLength();//获得文件总长度
     77                     int len=0,total_length=0;
     78                     byte[] data=new byte[1024];//每次读取的内容
     79                     while((len=inputStream.read(data))!=-1){
     80                         total_length+=len;
     81                         int value=(int)((total_length/(float)file_Length)*100);
     82                         publishProgress(value);//发布刻度到onProgressUpdate
     83                         byteArrayOutputStream.write(data, 0, len);
     84                     }
     85                     byte []result=byteArrayOutputStream.toByteArray();
     86                     bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);//将数据转换成bitmap对象
     87                 }
     88 
     89             } catch (Exception e) {
     90                 // TODO: handle exception
     91                 e.printStackTrace();
     92             }
     93             finally{
     94                 if(inputStream!=null){
     95                     try {
     96                         inputStream.close();
     97                     } catch (IOException e) {
     98                         // TODO Auto-generated catch block
     99                         e.printStackTrace();
    100                     }
    101                 }
    102             }
    103             return bitmap;
    104         }
    105 
    106         @Override
    107         protected void onProgressUpdate(Integer... values) {
    108             // TODO Auto-generated method stub
    109             super.onProgressUpdate(values);
    110             progressDialog.setProgress(values[0]);
    111         }
    112 
    113         @Override
    114         protected void onPostExecute(Bitmap result) {
    115             // TODO Auto-generated method stub
    116             super.onPostExecute(result);
    117             imageView.setImageBitmap(result);
    118             progressDialog.dismiss();
    119         }
    120 
    121     }
    122 
    123     @Override
    124     public boolean onCreateOptionsMenu(Menu menu) {
    125         // Inflate the menu; this adds items to the action bar if it is present.
    126         getMenuInflater().inflate(R.menu.main, menu);
    127         return true;
    128     }
    129 
    130     @Override
    131     public boolean onOptionsItemSelected(MenuItem item) {
    132         // Handle action bar item clicks here. The action bar will
    133         // automatically handle clicks on the Home/Up button, so long
    134         // as you specify a parent activity in AndroidManifest.xml.
    135         int id = item.getItemId();
    136         if (id == R.id.action_settings) {
    137             return true;
    138         }
    139         return super.onOptionsItemSelected(item);
    140     }
    141 }
    View Code

    Handler:异步处理大师发送、处理消息,

    Handler扮演了往MQ上添加消息和处理消息的角色(只处理由自己发出的消息),即:

    通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。

    handler创建时会关联一个looper,默认的构造方法将关联当前线程的looper,不过这也是可以set的。

    andriod提供了Handler 和 Looper 来满足线程间的通信。

    Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。

    1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。 
    2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。
    3) Message Queue(消息队列):用来存放线程放入的消息。

     4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。 

    1.Handler创建消息

     每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中引入了消息池。

    Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。

    使用消息池的好处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。

    消息池提高了消息对象的复用,减少系统垃圾回收的次数。消息的创建流程如图1所示。

    2.Handler发送消息

    主要接受子线程发送的数据, 并用此数据配合主线程更新UI.

    解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程,默认有一个消息队列) , 主线程为管理界面中的UI控件,进行事件分发,

    比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如:

    联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会

    出现假死现象,如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭".

    这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程是线程不安全的,也就是说,

    更新UI只能在主线程中更新,子线程中操作是危险的.

    这个时候,Handler就出现了.,来解决这个复杂的问题 , 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据,

    这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。

    UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。

    使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。

    Looper初始化的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
    Handler、Looper、MessageQueue的初始化流程如图2所示:

                                 图1                                                                  图2                                                              图3

    一个最简单的异步任务例子:从网上下载一副图片(handler+message)

      1 package com.example.android_03handler;
      2 
      3 import org.apache.http.HttpResponse;
      4 import org.apache.http.client.HttpClient;
      5 import org.apache.http.client.methods.HttpGet;
      6 import org.apache.http.impl.client.DefaultHttpClient;
      7 import org.apache.http.util.EntityUtils;
      8 
      9 import android.app.Activity;
     10 import android.app.ProgressDialog;
     11 import android.graphics.Bitmap;
     12 import android.graphics.BitmapFactory;
     13 import android.os.Bundle;
     14 import android.os.Handler;
     15 import android.os.Message;
     16 import android.view.Menu;
     17 import android.view.MenuItem;
     18 import android.view.View;
     19 import android.widget.Button;
     20 import android.widget.ImageView;
     21 
     22 public class MainActivity extends Activity {
     23     private Button button;
     24     private ImageView imageView;
     25     private String image_Path = "http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg";
     26     private final int IS_FINISHED=1;
     27     private ProgressDialog progressDialog;
     28     /**
     29      * Handler必须开启一个子线程
     30      * 该子线程必须通过Message传递数据给Handler
     31      */
     32     private Handler handler=new Handler(){
     33 
     34         @Override
     35         public void handleMessage(Message msg) {
     36             // TODO Auto-generated method stub
     37             super.handleMessage(msg);
     38             byte[] data=(byte[]) msg.obj;//将message发送回来的数据强制转换成字节数组
     39             Bitmap bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);
     40             imageView.setImageBitmap(bitmap);
     41             if(msg.what==IS_FINISHED){
     42                 progressDialog.dismiss();
     43             }
     44         }
     45         
     46     };
     47     
     48     public class myThread implements Runnable{
     49 
     50         //完成耗时任务操作
     51         @Override
     52         public void run() {
     53             // TODO Auto-generated method stub
     54             HttpClient httpClient = new DefaultHttpClient();
     55             HttpGet httpGet = new HttpGet(image_Path);
     56             HttpResponse httpResponse =null;
     57             try {
     58                  httpResponse = httpClient.execute(httpGet);
     59                  if (httpResponse.getStatusLine().getStatusCode() == 200) {
     60                      byte[] data=EntityUtils.toByteArray(httpResponse.getEntity());
     61                      Message message=Message.obtain();
     62                      message.obj=data;
     63                      message.what=IS_FINISHED;
     64                      handler.sendMessage(message);
     65                      
     66                  }
     67             } catch (Exception e) {
     68                 // TODO: handle exception
     69                 e.printStackTrace();
     70             }
     71         }
     72         
     73     }
     74     @Override
     75     protected void onCreate(Bundle savedInstanceState) {
     76         super.onCreate(savedInstanceState);
     77         setContentView(R.layout.activity_main);
     78         button = (Button) this.findViewById(R.id.button1);
     79         imageView = (ImageView) this.findViewById(R.id.imageView1);
     80         progressDialog=new ProgressDialog(this);
     81         progressDialog.setTitle("提示");
     82         progressDialog.setMessage("downloading.....");
     83         progressDialog.setCancelable(false);
     84         button.setOnClickListener(new View.OnClickListener() {
     85             
     86             @Override
     87             public void onClick(View v) {
     88                 // TODO Auto-generated method stub
     89                 new Thread(new myThread()).start();
     90                 progressDialog.show();
     91             }
     92         });
     93     }
     94 
     95     @Override
     96     public boolean onCreateOptionsMenu(Menu menu) {
     97         // Inflate the menu; this adds items to the action bar if it is present.
     98         getMenuInflater().inflate(R.menu.main, menu);
     99         return true;
    100     }
    101 
    102     @Override
    103     public boolean onOptionsItemSelected(MenuItem item) {
    104         // Handle action bar item clicks here. The action bar will
    105         // automatically handle clicks on the Home/Up button, so long
    106         // as you specify a parent activity in AndroidManifest.xml.
    107         int id = item.getItemId();
    108         if (id == R.id.action_settings) {
    109             return true;
    110         }
    111         return super.onOptionsItemSelected(item);
    112     }
    113 }
    View Code

    message简单代码(不建议使用new生成消息,建议使用message.obtain()或者Handler.obtainMessage(....))

      1 package com.example.android_03message;
      2 
      3 import android.app.Activity;
      4 import android.os.Bundle;
      5 import android.os.Handler;
      6 import android.os.Message;
      7 import android.view.Menu;
      8 import android.view.MenuItem;
      9 import android.view.View;
     10 import android.widget.Button;
     11 
     12 public class MainActivity extends Activity {
     13     private Button button;
     14     private Handler handler=new Handler(){
     15 
     16         @Override
     17         public void handleMessage(Message msg) {
     18             // TODO Auto-generated method stub
     19             super.handleMessage(msg);
     20             int arg1=msg.arg1;
     21             int arg2=msg.arg2;
     22             int what=msg.what;
     23             Object obj=msg.obj;
     24             System.out.println("-->"+arg1+"-->"+arg2+"-->"+what+"-->"+obj);
     25             Bundle bundle=msg.getData();
     26             System.out.println(bundle.getStringArray("str").length);
     27         }
     28         
     29     };
     30     public class myThread implements Runnable{
     31 
     32         @Override
     33         public void run() {
     34             // TODO Auto-generated method stub
     35             //第一种方式
     36              /*Message message=Message.obtain();
     37              message.arg1=1;
     38              message.arg2=2;
     39              message.what=3;
     40              message.obj="mlj";
     41              handler.sendMessage(message);*/
     42             //第二种方式,源码中提示,默认执行了message.target=handler表明将消息交给某个handler去发送,
     43             //因此与第一种发送消息方式不同
     44             /* Message message=Message.obtain(handler);
     45              message.arg1=1;
     46              message.arg2=2;
     47              message.what=3;
     48              message.obj="mlj";
     49              message.sendToTarget();*/
     50             //第三种方式Message.obtain(handler,what);
     51             /* Message message=Message.obtain(handler,3);
     52              message.arg1=1;
     53              message.arg2=2;
     54              message.obj="mlj";
     55              message.sendToTarget();*/
     56             //第四种方式Message.obtain(handler,what,obj);
     57             /*Message message=Message.obtain(handler,3,"mlj");
     58              message.arg1=1;
     59              message.arg2=2;
     60              message.sendToTarget();*/
     61             //第五种方式Message.obtain(handler,what,arg1,arg2,obj);
     62             Message message=Message.obtain(handler,3,1,2,"mlj");
     63             //在传基本数据之外还可以通过setData传一些复杂数据
     64             Bundle  bundle=new Bundle();
     65             bundle.putStringArray("str", new String []{"mlj","mlj","mlj"});
     66             message.setData(bundle);
     67              message.sendToTarget();
     68             
     69         }
     70         
     71     }
     72     @Override
     73     protected void onCreate(Bundle savedInstanceState) {
     74         super.onCreate(savedInstanceState);
     75         setContentView(R.layout.activity_main);
     76         button = (Button) this.findViewById(R.id.button1);
     77         button.setOnClickListener(new View.OnClickListener() {
     78             
     79             @Override
     80             public void onClick(View v) {
     81                 // TODO Auto-generated method stub
     82                 new Thread(new myThread()).start();
     83             }
     84         });
     85     }
     86 
     87     @Override
     88     public boolean onCreateOptionsMenu(Menu menu) {
     89         // Inflate the menu; this adds items to the action bar if it is present.
     90         getMenuInflater().inflate(R.menu.main, menu);
     91         return true;
     92     }
     93 
     94     @Override
     95     public boolean onOptionsItemSelected(MenuItem item) {
     96         // Handle action bar item clicks here. The action bar will
     97         // automatically handle clicks on the Home/Up button, so long
     98         // as you specify a parent activity in AndroidManifest.xml.
     99         int id = item.getItemId();
    100         if (id == R.id.action_settings) {
    101             return true;
    102         }
    103         return super.onOptionsItemSelected(item);
    104     }
    105 }
    View Code

    handler的send(在线程内部发送消息方式)和post(new Runnable()...)两种发送消息方式的简单代码

     1 package com.example.android_03handler_message;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.os.Handler;
     6 import android.os.Message;
     7 import android.view.Menu;
     8 import android.view.MenuItem;
     9 import android.view.View;
    10 import android.view.View.OnClickListener;
    11 import android.widget.Button;
    12 
    13 public class MainActivity extends Activity implements OnClickListener{
    14     private Button button;
    15     private Button button2;
    16     private Handler handler=new Handler(){
    17 
    18         @Override
    19         public void handleMessage(Message msg) {
    20             // TODO Auto-generated method stub
    21             super.handleMessage(msg);
    22             System.out.println("-->"+msg.what);
    23         }
    24         
    25     };
    26     @Override
    27     protected void onCreate(Bundle savedInstanceState) {
    28         super.onCreate(savedInstanceState);
    29         setContentView(R.layout.activity_main);
    30         button = (Button) this.findViewById(R.id.button1);
    31         button2 = (Button) this.findViewById(R.id.button2);
    32         button.setOnClickListener(this);
    33         button2.setOnClickListener(this);
    34     }
    35 
    36     @Override
    37     public boolean onCreateOptionsMenu(Menu menu) {
    38         // Inflate the menu; this adds items to the action bar if it is present.
    39         getMenuInflater().inflate(R.menu.main, menu);
    40         return true;
    41     }
    42 
    43     @Override
    44     public boolean onOptionsItemSelected(MenuItem item) {
    45         // Handle action bar item clicks here. The action bar will
    46         // automatically handle clicks on the Home/Up button, so long
    47         // as you specify a parent activity in AndroidManifest.xml.
    48         int id = item.getItemId();
    49         if (id == R.id.action_settings) {
    50             return true;
    51         }
    52         return super.onOptionsItemSelected(item);
    53     }
    54 
    55     @Override
    56     public void onClick(View v) {
    57         // TODO Auto-generated method stub
    58         switch (v.getId()) {
    59         case R.id.button1:
    60             new Thread(new Runnable() {
    61                 
    62                 @Override
    63                 public void run() {
    64                     // TODO Auto-generated method stub
    65                     //handler.sendEmptyMessage(3);
    66                     //handler.sendEmptyMessageAtTime(4, 1000);
    67                     handler.sendEmptyMessageDelayed(3, 3000);
    68                 }
    69             }).start();
    70             break;
    71         case R.id.button2:
    72              handler.post(new Runnable() {
    73                 
    74                 @Override
    75                 public void run() {
    76                     // TODO Auto-generated method stub
    77                     handler.sendEmptyMessageDelayed(3, 4000);
    78                 }
    79             });
    80             break;
    81         default:
    82             break;
    83         }
    84     }
    85 }
    View Code

    Looper:

    字面意思是“循环者”,它被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。

    在程序开发中(尤其是GUI开发中),我们经常会需要一个线程不断循环,一旦有新任务则执行,执行完继续等待下一个任务,这就是Looper线程。

    使用Looper类创建Looper线程很简单:

    public class LooperThread extends Thread {
        @Override
        public void run() {
            // 将当前线程初始化为Looper线程
            Looper.prepare();
            
            // ...其他处理,如实例化handler
            
            // 开始循环处理消息队列
            Looper.loop();
        }
    }
    View Code

    Looper.prepare()之后线程就升级为Looper线程了,线程中有一个Looper对象,它的内部维护了一个消息队列MQ。注意,一个Thread只能有一个Looper对象

    prepare()背后的工作方式一目了然,其核心就是将looper对象定义为ThreadLocal

    调用loop方法后,Looper线程就开始真正工作了,它不断从自己的MQ中取出队头的消息(也叫任务)执行。

    除了prepare()和loop()方法,Looper类还提供了一些有用的方法,比如:

    Looper.myLooper()得到当前线程looper对象:

    1 public static final Looper myLooper() {
    2         // 在任意线程调用Looper.myLooper()返回的都是那个线程的looper
    3         return (Looper)sThreadLocal.get();
    4     }
    View Code

    getThread()得到looper对象所属线程:

    1 public Thread getThread() {
    2         return mThread;
    3     }
    View Code

    quit()方法结束looper循环:

    1 public void quit() {
    2         // 创建一个空的message,它的target为NULL,表示结束循环消息
    3         Message msg = Message.obtain();
    4         // 发出消息
    5         mQueue.enqueueMessage(msg, 0);
    6     }
    View Code

    简单的looper代码:

     1 package com.example.android_08looper;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.os.Handler;
     6 import android.os.Looper;
     7 import android.os.Message;
     8 import android.view.Menu;
     9 import android.view.MenuItem;
    10 import android.view.View;
    11 import android.widget.Button;
    12 import android.widget.TextView;
    13 
    14 public class MainActivity extends Activity {
    15 
    16     private  Button button1;
    17     private TextView textView1;
    18     private myHandler mHandler;
    19     @Override
    20     protected void onCreate(Bundle savedInstanceState) {
    21         super.onCreate(savedInstanceState);
    22         setContentView(R.layout.activity_main);
    23         button1=(Button)this.findViewById(R.id.button1);
    24         textView1=(TextView)this.findViewById(R.id.textView1);
    25         //使用无参构造方法时handler并未与looper关联,但是为什么可以发送并接收消息呢?
    26         //原因是Activity中默认有一个Looper对象来处理子线程发送的消息,其实相当于一下内容
    27         //Looper looper=Looper.myLooper();//从UI主线程中得到looper
    28         //mHandler=new myHandler(looper);
    29         Looper looper=Looper.myLooper();
    30         mHandler=new myHandler();
    31         button1.setOnClickListener(new View.OnClickListener() {
    32             
    33             @Override
    34             public void onClick(View v) {
    35                 // TODO Auto-generated method stub
    36                 new Thread(new myThread()).start();//在主线程中开启一个子线程
    37             }
    38         });
    39     }
    40 
    41     public class myThread implements Runnable{
    42 
    43         @Override
    44         public void run() {
    45             // TODO Auto-generated method stub
    46             Message message=Message.obtain();
    47             message.obj="mlj";
    48             mHandler.sendMessage(message);
    49         }
    50         
    51     }
    52     public class myHandler extends Handler{
    53 
    54         public myHandler(Looper looper) {
    55             super(looper);
    56             // TODO Auto-generated constructor stub
    57         }
    58         public myHandler() {
    59         
    60         }
    61 
    62 
    63         @Override
    64         public void handleMessage(Message msg) {
    65             // TODO Auto-generated method stub
    66             super.handleMessage(msg);
    67             textView1.setText("-接收消息->>"+msg.obj);
    68         }
    69         
    70     }
    71     @Override
    72     public boolean onCreateOptionsMenu(Menu menu) {
    73         // Inflate the menu; this adds items to the action bar if it is present.
    74         getMenuInflater().inflate(R.menu.main, menu);
    75         return true;
    76     }
    77 
    78     @Override
    79     public boolean onOptionsItemSelected(MenuItem item) {
    80         // Handle action bar item clicks here. The action bar will
    81         // automatically handle clicks on the Home/Up button, so long
    82         // as you specify a parent activity in AndroidManifest.xml.
    83         int id = item.getItemId();
    84         if (id == R.id.action_settings) {
    85             return true;
    86         }
    87         return super.onOptionsItemSelected(item);
    88     }
    89 }
    View Code

    在以上例子中,如果handler的实例化脱离了UI主线程,而在子线程中实例化的话,就无法使用Activity中默认的looper对象,

    就需要手工开启Looper,代码如下:

     1 package com.example.android_08looper;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.os.Handler;
     6 import android.os.Looper;
     7 import android.os.Message;
     8 import android.view.Menu;
     9 import android.view.MenuItem;
    10 import android.view.View;
    11 import android.widget.Button;
    12 import android.widget.TextView;
    13 
    14 public class MainActivity extends Activity {
    15 
    16     private  Button button1;
    17     private TextView textView1;
    18     private Handler mHandler;
    19     @Override
    20     protected void onCreate(Bundle savedInstanceState) {
    21         super.onCreate(savedInstanceState);
    22         setContentView(R.layout.activity_main);
    23         button1=(Button)this.findViewById(R.id.button1);
    24         textView1=(TextView)this.findViewById(R.id.textView1);
    25         new Thread(new myThread()).start();
    26         button1.setOnClickListener(new View.OnClickListener() {
    27             
    28             @Override
    29             public void onClick(View v) {
    30                 // TODO Auto-generated method stub
    31                 Message message=Message.obtain();
    32                 message.obj="mlj";
    33                 mHandler.sendMessage(message);
    34             }
    35         });
    36     }
    37 
    38     public class myThread implements Runnable{
    39 
    40         @Override
    41         public void run() {
    42             // TODO Auto-generated method stub
    43             Looper.prepare();
    44             mHandler=new Handler(){
    45 
    46                 @Override
    47                 public void handleMessage(Message msg) {
    48                     // TODO Auto-generated method stub
    49                     super.handleMessage(msg);
    50                     //textView1.setText("--->>接收UI主线程的消息"+msg.obj);//在子线程中无法更新UI所以改成以下语句
    51                     System.out.println("--->>接收UI主线程的消息"+msg.obj);
    52                 }
    53                 
    54             };
    55             Looper.loop();
    56         }
    57         
    58     }
    59     @Override
    60     public boolean onCreateOptionsMenu(Menu menu) {
    61         // Inflate the menu; this adds items to the action bar if it is present.
    62         getMenuInflater().inflate(R.menu.main, menu);
    63         return true;
    64     }
    65 
    66     @Override
    67     public boolean onOptionsItemSelected(MenuItem item) {
    68         // Handle action bar item clicks here. The action bar will
    69         // automatically handle clicks on the Home/Up button, so long
    70         // as you specify a parent activity in AndroidManifest.xml.
    71         int id = item.getItemId();
    72         if (id == R.id.action_settings) {
    73             return true;
    74         }
    75         return super.onOptionsItemSelected(item);
    76     }
    77 }
    View Code

    总结几点:

    1.每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal

    2.Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行

    3.Looper使一个线程变成Looper线程。

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

    综合案例(图文混排):客户端(AsyncTask,Handler,Message,listView)+服务器端,未缓存

    服务器端最终返回给客户端的是jsonString,内容是:

    1 {"products":[{"proprice":"5","proaddress":"河南","proimage":"1.jpg","proname":"苹果","proid":"4a6c8e"},{"proprice":"2","proaddress":"北京","proimage":"1.jpg","proname":"猕猴桃","proid":"5fd850"},{"proprice":"4","proaddress":"广州","proimage":"1.jpg","proname":"香蕉","proid":"7c39b7"},{"proprice":"1","proaddress":"广州","proimage":"1.jpg","proname":"","proid":"850995"},{"proprice":"3","proaddress":"北京","proimage":"1.jpg","proname":"西瓜","proid":"be3314"},{"proprice":"7","proaddress":"上海","proimage":"1.jpg","proname":"桃子","proid":"c84833"}]} 
    View Code

    客户端源文件目录如图:

     步骤:

    第一步:在布局文件中添加listView

     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:paddingBottom="@dimen/activity_vertical_margin"
     6     android:paddingLeft="@dimen/activity_horizontal_margin"
     7     android:paddingRight="@dimen/activity_horizontal_margin"
     8     android:paddingTop="@dimen/activity_vertical_margin"
     9     tools:context="com.example.android_08handler_product.MainActivity" >
    10 
    11     <ListView
    12         android:id="@+id/listView1"
    13         android:layout_width="match_parent"
    14         android:layout_height="wrap_content"
    15         android:layout_alignParentTop="true"
    16         android:layout_centerHorizontal="true" >
    17     </ListView>
    18 
    19 </RelativeLayout>
    View Code

    第二步:在清单文件中添加网络授权

    1  <uses-permission android:name="android.permission.INTERNET"/>
    View Code

    第三步:定义一个公共类CommonURL.java,存放客户端访问的网络地址

    1 package com.example.android_08handler_product;
    2 
    3 public class CommonURL {
    4 
    5     //访问服务器产品url 
    6      static String Pro_URL="http://122.206.79.193:8080/xianfengProject/servlet/JsonAction?action_flag=more";
    7     //访问服务器产品图片url 
    8      static String Pro_ImgURL="http://122.206.79.193:8080/xianfengProject/upload/";
    9 }
    View Code

    第四步:编写主程序

    注:图文混排时,不建议文字和图片在同一线程中出现或解决,一般是先处理文字再处理图片。

    4.1 定义listView控件并取得 

    4.2为listView定义适配器(全局的)并在oncreate()方法中初始化,通常分以下几步

    1.声明Context context,LayoutInflater layoutInflater两个变量并在构造方法中取值:this.**=**;

    2.提供void setData()方法,由于取json数据时,数据类型是map类型,因此在适配器中需定义全局变量List<Map<String,Object>> list=null,

    并在该方法中设置 this.list=list;

    3. 完成适配器中除getView()方法以外的其他方法;

    4.为适配器定义布局文件item.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent" >
     5 
     6     <ImageView
     7         android:id="@+id/imageView1"
     8         android:layout_width="wrap_content"
     9         android:layout_height="wrap_content"
    10         android:layout_alignParentLeft="true"
    11         android:layout_alignParentTop="true"
    12         android:layout_marginLeft="16dp"
    13         android:src="@drawable/ic_launcher" />
    14 
    15     <TextView
    16         android:id="@+id/textView1"
    17         android:layout_width="wrap_content"
    18         android:layout_height="wrap_content"
    19         android:layout_alignParentTop="true"
    20         android:layout_toRightOf="@+id/imageView1"
    21         android:text="TextView" />
    22 
    23     <TextView
    24         android:id="@+id/textView2"
    25         android:layout_width="wrap_content"
    26         android:layout_height="wrap_content"
    27         android:layout_alignLeft="@+id/textView1"
    28         android:layout_below="@+id/textView1"
    29         android:text="TextView" />
    30 
    31     <TextView
    32         android:id="@+id/textView3"
    33         android:layout_width="wrap_content"
    34         android:layout_height="wrap_content"
    35         android:layout_alignLeft="@+id/textView2"
    36         android:layout_below="@+id/textView2"
    37         android:text="TextView" />
    38 
    39 </RelativeLayout>
    View Code

    5. 完成适配器中getView()方法;

     1 @Override
     2         public View getView(int position, View convertView, ViewGroup parent) {
     3             // TODO Auto-generated method stub
     4             View view=null;
     5             if(convertView==null){
     6                 view=layoutInflater.inflate(R.layout.item, null);
     7             }
     8             else
     9                 view=convertView;
    10             TextView name=(TextView)view.findViewById(R.id.textView1);
    11             TextView address=(TextView)view.findViewById(R.id.textView2);
    12             TextView price=(TextView)view.findViewById(R.id.textView3);
    13             final ImageView imageView=(ImageView)view.findViewById(R.id.imageView1);
    14             //接下来需要给name address price赋值成从服务器上取下来的数据,这就需要定义异步任务
    15             name.setText(list.get(position).get("proname").toString());
    16             address.setText(list.get(position).get("proaddress").toString());
    17             price.setText(list.get(position).get("proprice").toString());
    18          //图片待会儿再处理
    19             return view;
    20         }
    View Code

    由于在5中需要对name  address price image赋值,这些值是从服务器取下来的json数据并解析后传回来的,这就需要定义异步任务AsyncTask了

    4.3 定义异步任务

    1.通常需要定义一个ProgressDialog并在oncreate方法中初始化

    1     dialog=new ProgressDialog(this);
    2     dialog.setTitle("提示");
    3     dialog.setMessage("正在下载,请稍后......");
    View Code

    2.定义异步任务,实现3个方法

     1     public class myTask extends AsyncTask<String, Void, List<Map<String,Object>>>{
     2 
     3         @Override
     4         protected void onPreExecute() {
     5             // TODO Auto-generated method stub
     6             dialog.show();
     7             super.onPreExecute();
     8         }
     9 
    10         @Override
    11         protected void onPostExecute(List<Map<String, Object>> result) {
    12             // TODO Auto-generated method stub
    13             super.onPostExecute(result);
    14             adapter.setData(result);
    15             listView.setAdapter(adapter);
    16             adapter.notifyDataSetChanged();
    17             dialog.dismiss();
    18             
    19         }
    20 
    21         @Override
    22         protected List<Map<String, Object>> doInBackground(String... params) {
    23             // TODO Auto-generated method stub
    24             //list 服务器返回的最终经过解析后的json数据
    25             List<Map<String, Object>> list=new ArrayList<Map<String,Object>>();
    26             //连接网络 获取json数据并解析
    27             try {
    28                 HttpClient client=new DefaultHttpClient();
    29                 //HttpGet httpGet=new HttpGet(params[0]);//不建议使用 因为大小受限制
    30                 HttpPost httpPost=new HttpPost(params[0]);
    31                 HttpResponse response=client.execute(httpPost);
    32                 if(response.getStatusLine().getStatusCode()==200){
    33                     String jsonString=EntityUtils.toString(response.getEntity(), "utf-8");
    34                     //以上获取数据
    35                     //以下解析数据
    36                     JSONObject jsonObject=new JSONObject(jsonString);//返回的数据key为products,Value为数组,数组中的每个元素又是jsonObject
    37                     JSONArray jsonArray=jsonObject.getJSONArray("products");
    38                     for (int i = 0; i < jsonArray.length(); i++) {
    39                         JSONObject jsonObject2=jsonArray.getJSONObject(i);
    40                         Map<String,Object> map=new HashMap<String, Object>();
    41                         Iterator<String> iterator=jsonObject2.keys();
    42                         while(iterator.hasNext()){
    43                             String key=iterator.next();
    44                             Object val=jsonObject2.get(key);
    45                             map.put(key, val);
    46                         }
    47                         list.add(map);
    48                     }
    49                 }
    50                 
    51             } catch (Exception e) {
    52                 // TODO: handle exception
    53                 e.printStackTrace();
    54             }
    55             return list;
    56         }
    57         
    58     }
    59     @Override
    60     
    View Code

    3.在oncreate()方法中开启任务,传递的参数是CommonURL中的地址

    1 new myTask().execute(CommonURL.Pro_URL);
    View Code

     在onpostExcute()方法执行时,通过适配器的setData方法填充适配器,并为listView绑定数据源

    1 protected void onPostExecute(List<Map<String, Object>> result) {
    2             // TODO Auto-generated method stub
    3             super.onPostExecute(result);
    4             adapter.setData(result);
    5             listView.setAdapter(adapter);
    6             adapter.notifyDataSetChanged();
    7             dialog.dismiss();
    8             
    9         }
    View Code

    之后 就得回到第四步4.2的最后一小步,即更新UI

    1 name.setText(list.get(position).get("proname").toString());
    2             address.setText(list.get(position).get("proaddress").toString());
    3             price.setText(list.get(position).get("proprice").toString());
    View Code

    ----------接下来得用接口回调来加载图片---------------

    需要专门定义一个用来处理图片的类DownLoadImg.java,该类包括:

    一个用来传递图片地址的构造方法,一个提供得到图片方法的接口,和一个下载图片、开启子线程返回消息给handler的方法(其参数是回调接口的一个对象)

    该类接收activity传过来的图片路径并方法中开启一个子线程中下载图片作为消息返回给handler处理,handler的处理方式是通过回调对象获得该图片的引用,

    然后在activity中调用该方法时,需要new一个接口对象作为参数,该参数是一个匿名内部类,在该类的实现接口方法中即可获得图片

    因为该类需要开启一个子线程,得到图片

    接口回调:定义一个接口,该接口提供了一个得到图片的方法getDrawable,方法参数为Drawable类型

    1 public interface ImgCallBack{
    2         public void getDrawable(Drawable drawable);
    3     }
    View Code

    最终代码:

    MainActivity:

      1 package com.example.android_08handler_product;
      2 
      3 import java.util.ArrayList;
      4 import java.util.HashMap;
      5 import java.util.Iterator;
      6 import java.util.List;
      7 import java.util.Map;
      8 
      9 import org.apache.http.HttpResponse;
     10 import org.apache.http.client.HttpClient;
     11 import org.apache.http.client.methods.HttpPost;
     12 import org.apache.http.impl.client.DefaultHttpClient;
     13 import org.apache.http.util.EntityUtils;
     14 import org.json.JSONArray;
     15 import org.json.JSONObject;
     16 
     17 import android.app.Activity;
     18 import android.app.ProgressDialog;
     19 import android.content.Context;
     20 import android.graphics.drawable.Drawable;
     21 import android.os.AsyncTask;
     22 import android.os.Bundle;
     23 import android.view.LayoutInflater;
     24 import android.view.Menu;
     25 import android.view.MenuItem;
     26 import android.view.View;
     27 import android.view.ViewGroup;
     28 import android.widget.BaseAdapter;
     29 import android.widget.ImageView;
     30 import android.widget.ListView;
     31 import android.widget.TextView;
     32 
     33 import com.example.android_08handler_product.DownLoadImg.ImgCallBack;
     34 
     35 public class MainActivity extends Activity {
     36 
     37     private ListView listView;
     38     private ProgressDialog dialog;
     39     private myAdapter adapter;
     40     @Override
     41     protected void onCreate(Bundle savedInstanceState) {
     42         super.onCreate(savedInstanceState);
     43         setContentView(R.layout.activity_main);
     44         listView=(ListView)this.findViewById(R.id.listView1);
     45         dialog=new ProgressDialog(this);
     46         dialog.setTitle("提示");
     47         dialog.setMessage("正在下载,请稍后......");
     48         adapter=new myAdapter(this);
     49         new myTask().execute(CommonURL.Pro_URL);
     50     }
     51 
     52     public class myAdapter extends BaseAdapter{
     53 
     54         private Context context;
     55         private LayoutInflater layoutInflater;
     56         private List<Map<String,Object>> list=null;//存放最终解析过的json数据
     57         public  myAdapter(){
     58             
     59         }
     60         public  myAdapter(Context context){
     61             this.context=context;
     62             layoutInflater=layoutInflater.from(context);
     63         }
     64          public void setData(List<Map<String,Object>> list){
     65              this.list=list;
     66          }
     67        @Override
     68         public int getCount() {
     69             // TODO Auto-generated method stub
     70             return list.size();
     71         }
     72 
     73         @Override
     74         public Object getItem(int position) {
     75             // TODO Auto-generated method stub
     76             return list.get(position);
     77         }
     78 
     79         @Override
     80         public long getItemId(int position) {
     81             // TODO Auto-generated method stub
     82             return position;
     83         }
     84 
     85         @Override
     86         public View getView(int position, View convertView, ViewGroup parent) {
     87             // TODO Auto-generated method stub
     88             View view=null;
     89             if(convertView==null){
     90                 view=layoutInflater.inflate(R.layout.item, null);
     91             }
     92             else
     93                 view=convertView;
     94             TextView name=(TextView)view.findViewById(R.id.textView1);
     95             TextView address=(TextView)view.findViewById(R.id.textView2);
     96             TextView price=(TextView)view.findViewById(R.id.textView3);
     97             final ImageView imageView=(ImageView)view.findViewById(R.id.imageView1);
     98             //接下来需要给name address price赋值成从服务器上取下来的数据,这就需要定义异步任务
     99             name.setText(list.get(position).get("proname").toString());
    100             address.setText(list.get(position).get("proaddress").toString());
    101             price.setText(list.get(position).get("proprice").toString());
    102             DownLoadImg downLoadImg=new DownLoadImg(CommonURL.Pro_ImgURL+list.get(position).get("proimage").toString());
    103             downLoadImg.loadImg(new ImgCallBack() {
    104                 
    105                 @Override
    106                 public void getDrawable(Drawable drawable) {
    107                     // TODO Auto-generated method stub
    108                     imageView.setImageDrawable(drawable);
    109                 }
    110             });
    111             return view;
    112         }
    113         
    114     }
    115     public class myTask extends AsyncTask<String, Void, List<Map<String,Object>>>{
    116 
    117         @Override
    118         protected void onPreExecute() {
    119             // TODO Auto-generated method stub
    120             dialog.show();
    121             super.onPreExecute();
    122         }
    123 
    124         @Override
    125         protected void onPostExecute(List<Map<String, Object>> result) {
    126             // TODO Auto-generated method stub
    127             super.onPostExecute(result);
    128             adapter.setData(result);
    129             listView.setAdapter(adapter);
    130             adapter.notifyDataSetChanged();
    131             dialog.dismiss();
    132             
    133         }
    134 
    135         @Override
    136         protected List<Map<String, Object>> doInBackground(String... params) {
    137             // TODO Auto-generated method stub
    138             //list 服务器返回的最终经过解析后的json数据
    139             List<Map<String, Object>> list=new ArrayList<Map<String,Object>>();
    140             //连接网络 获取json数据并解析
    141             try {
    142                 HttpClient client=new DefaultHttpClient();
    143                 //HttpGet httpGet=new HttpGet(params[0]);//不建议使用 因为大小受限制
    144                 HttpPost httpPost=new HttpPost(params[0]);
    145                 HttpResponse response=client.execute(httpPost);
    146                 if(response.getStatusLine().getStatusCode()==200){
    147                     String jsonString=EntityUtils.toString(response.getEntity(), "utf-8");
    148                     //以上获取数据
    149                     //以下解析数据
    150                     JSONObject jsonObject=new JSONObject(jsonString);//返回的数据key为products,Value为数组,数组中的每个元素又是jsonObject
    151                     JSONArray jsonArray=jsonObject.getJSONArray("products");
    152                     for (int i = 0; i < jsonArray.length(); i++) {
    153                         JSONObject jsonObject2=jsonArray.getJSONObject(i);
    154                         Map<String,Object> map=new HashMap<String, Object>();
    155                         Iterator<String> iterator=jsonObject2.keys();
    156                         while(iterator.hasNext()){
    157                             String key=iterator.next();
    158                             Object val=jsonObject2.get(key);
    159                             map.put(key, val);
    160                         }
    161                         list.add(map);
    162                     }
    163                 }
    164                 
    165             } catch (Exception e) {
    166                 // TODO: handle exception
    167                 e.printStackTrace();
    168             }
    169             return list;
    170         }
    171         
    172     }
    173     @Override
    174     public boolean onCreateOptionsMenu(Menu menu) {
    175         // Inflate the menu; this adds items to the action bar if it is present.
    176         getMenuInflater().inflate(R.menu.main, menu);
    177         return true;
    178     }
    179 
    180     @Override
    181     public boolean onOptionsItemSelected(MenuItem item) {
    182         // Handle action bar item clicks here. The action bar will
    183         // automatically handle clicks on the Home/Up button, so long
    184         // as you specify a parent activity in AndroidManifest.xml.
    185         int id = item.getItemId();
    186         if (id == R.id.action_settings) {
    187             return true;
    188         }
    189         return super.onOptionsItemSelected(item);
    190     }
    191 }
    View Code

    DownLoadImg

     1 package com.example.android_08handler_product;
     2 
     3 import java.io.IOException;
     4 import java.io.InputStream;
     5 import java.net.MalformedURLException;
     6 import java.net.URL;
     7 
     8 import android.graphics.drawable.Drawable;
     9 import android.os.Handler;
    10 import android.os.Message;
    11 
    12 public class DownLoadImg {
    13 
    14     private String img_path;
    15     public DownLoadImg(String img_path) {
    16         // TODO Auto-generated constructor stub
    17         this.img_path=img_path;
    18     }
    19 
    20     public void loadImg(final ImgCallBack back){
    21         final Handler handler=new Handler(){
    22 
    23             @Override
    24             public void handleMessage(Message msg) {
    25                 // TODO Auto-generated method stub
    26                 super.handleMessage(msg);
    27                 back.getDrawable((Drawable)msg.obj);
    28             }
    29         };
    30         new Thread(new Runnable() {
    31             
    32             @Override
    33             public void run() {
    34                 InputStream is;
    35                 try {
    36                     is = new URL(img_path).openStream();
    37                     Drawable drawable=Drawable.createFromStream(is, "");
    38                     Message message=Message.obtain();
    39                     message.obj=drawable;
    40                     handler.sendMessage(message);
    41                 } catch (MalformedURLException e) {
    42                     // TODO Auto-generated catch block
    43                     e.printStackTrace();
    44                 } catch (IOException e) {
    45                     // TODO Auto-generated catch block
    46                     e.printStackTrace();
    47                 }
    48                 // TODO Auto-generated method stub
    49                 
    50             }
    51         }).start();
    52     }
    53     //接口的回调方式
    54     public interface ImgCallBack{
    55         public void getDrawable(Drawable drawable);
    56     }
    57 }
    View Code
  • 相关阅读:
    移动互联网实战--Apple的APNS桩推送服务的实现(1)
    移动互联网实战--社交游戏的排行榜设计和实现(2)
    移动互联网实战--社交游戏的排行榜设计和实现(1)
    Linux 线程--那一年, 我们一起忽视的pthread_join
    移动互联网实战--资源类APP的数据存储处理和优化
    Thrift 个人实战--RPC服务的发布订阅实现(基于Zookeeper服务)
    移动互联网实战--Web Restful API设计和基础架构
    Thrift 个人实战--Thrift RPC服务框架日志的优化
    Thrift 个人实战--Thrift 服务化 Client的改造
    Kafka集群副本分配算法解析
  • 原文地址:https://www.cnblogs.com/mlj5288/p/4960036.html
Copyright © 2020-2023  润新知