Android之AsyncTask的用法

为什么要使用AsyncTask?

在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。在单线程模型中始终要记住两条法则:
1. 不要阻塞UI线程
2. 确保只在UI线程中访问Android UI工具包
当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。
比如说从网上获取一个网页,在一个TextView中将其源代码显示出来,这种涉及到网络操作的程序一般都是需要开一个线程完成网络访问,但是在获得页面源码后,是不能直接在网络操作线程中调用TextView.setText()的.因为其他线程中是不能直接访问主UI线程成员 。

android提供了几种在其他线程中访问UI线程的方法。
Activity.runOnUiThread( Runnable )
View.post( Runnable )
View.postDelayed( Runnable, long )
Hanlder
这些类或方法同样会使你的代码很复杂很难理解。然而当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。

为了解决这个问题,Android 1.5提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单。相对来说AsyncTask更轻量级一些,适用于简单的异步处理,不需要借助线程和Handler即可实现。
AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。
  Params 启动任务执行的输入参数,比如HTTP请求的URL。
  Progress 后台任务执行的百分比。
  Result 后台执行任务最终返回的结果,比如String。


AsyncTask的执行分为四个步骤:
每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。
  1) 子类化AsyncTask
  2) 实现AsyncTask中定义的下面一个或几个方法
   onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。
   doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
   onProgressUpdate(Progress...),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
   onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.

为正确的使用AsyncTask类,以下是几条必须遵守的准则:
  1) Task的实例必须在UI thread中创建
  2) execute方法必须在UI thread中调用
  3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法
  4) 该task只能被执行一次,否则多次调用时将会出现异常
doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。


从网上获取一个网页,在一个TextView中将其源代码显示出来 

view plain print ?
  1. package cn.test;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.InputStream;  
  5. import java.util.ArrayList;  
  6.   
  7. import org.apache.http.HttpEntity;  
  8. import org.apache.http.HttpResponse;  
  9. import org.apache.http.client.HttpClient;  
  10. import org.apache.http.client.methods.HttpGet;  
  11. import org.apache.http.impl.client.DefaultHttpClient;  
  12.   
  13. import android.app.Activity;  
  14. import android.app.ProgressDialog;  
  15. import android.content.Context;  
  16. import android.content.DialogInterface;  
  17. import android.os.AsyncTask;  
  18. import android.os.Bundle;  
  19. import android.os.Handler;  
  20. import android.os.Message;  
  21. import android.view.View;  
  22. import android.widget.Button;  
  23. import android.widget.EditText;  
  24. import android.widget.TextView;  
  25.   
  26. public class NetworkActivity extends Activity{  
  27.     private TextView message;  
  28.     private Button open;  
  29.     private EditText url;  
  30.   
  31.     @Override  
  32.     public void onCreate(Bundle savedInstanceState) {  
  33.        super.onCreate(savedInstanceState);  
  34.        setContentView(R.layout.network);  
  35.        message= (TextView) findViewById(R.id.message);  
  36.        url= (EditText) findViewById(R.id.url);  
  37.        open= (Button) findViewById(R.id.open);  
  38.        open.setOnClickListener(new View.OnClickListener() {  
  39.            public void onClick(View arg0) {  
  40.               connect();  
  41.            }  
  42.        });  
  43.   
  44.     }  
  45.   
  46.     private void connect() {  
  47.         PageTask task = new PageTask(this);  
  48.         task.execute(url.getText().toString());  
  49.     }  
  50.   
  51.   
  52.     class PageTask extends AsyncTask<String, Integer, String> {  
  53.         ProgressDialog pdialog;  
  54.         public PageTask(Context context){  
  55.             pdialog = new ProgressDialog(context, 0);     
  56.             pdialog.setButton("cancel"new DialogInterface.OnClickListener() {  
  57.              public void onClick(DialogInterface dialog, int i) {  
  58.               dialog.cancel();  
  59.              }  
  60.             });  
  61.             pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {  
  62.              public void onCancel(DialogInterface dialog) {  
  63.               finish();  
  64.              }  
  65.             });  
  66.             pdialog.setCancelable(true);  
  67.             pdialog.setMax(100);  
  68.             pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
  69.             pdialog.show();  
  70.         }  
  71.           
  72.         //后台运行的方法 ,运行在非ui线程 可以执行耗时的操作   
  73.         @Override  
  74.         protected String doInBackground(String... params) {  
  75.   
  76.             try{  
  77.   
  78.                HttpClient client = new DefaultHttpClient();  
  79.                // params[0]代表连接的url  
  80.                HttpGet get = new HttpGet(params[0]);  
  81.                HttpResponse response = client.execute(get);  
  82.                HttpEntity entity = response.getEntity();  
  83.                long length = entity.getContentLength();  
  84.                InputStream is = entity.getContent();  
  85.                String s = null;  
  86.                if(is != null) {  
  87.                    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  88.   
  89.                    byte[] buf = new byte[128];  
  90.   
  91.                    int ch = -1;  
  92.   
  93.                    int count = 0;  
  94.   
  95.                    while((ch = is.read(buf)) != -1) {  
  96.   
  97.                       baos.write(buf, 0, ch);  
  98.   
  99.                       count += ch;  
  100.   
  101.                       if(length > 0) {  
  102.                           // 如果知道响应的长度,调用publishProgress()更新进度  
  103.                           publishProgress((int) ((count / (float) length) * 100));  
  104.                       }  
  105.   
  106.                       // 让线程休眠100ms  
  107.                       Thread.sleep(100);  
  108.                    }  
  109.                    s = new String(baos.toByteArray());              }  
  110.                // 返回结果  
  111.                return s;  
  112.             } catch(Exception e) {  
  113.                e.printStackTrace();  
  114.   
  115.             }  
  116.   
  117.             return null;  
  118.   
  119.         }  
  120.   
  121.         // 运行在主线程中,ui线程中, 在doInbackground执行完毕后执行  
  122.         @Override  
  123.         protected void onPostExecute(String result) {  
  124.             // 返回HTML页面的内容  
  125.             message.setText(result);  
  126.             pdialog.dismiss();   
  127.         }  
  128.   
  129.         //运行在ui线程中 ,在调用 doInbackground方法之前执行,  
  130.         @Override  
  131.         protected void onPreExecute() {  
  132.             // 任务启动,可以在这里显示一个对话框,这里简单处理  
  133.             message.setText(R.string.task_started);  
  134.         }  
  135.   
  136.         //在publishProgress方法被调用后执行  
  137.         @Override  
  138.         protected void onProgressUpdate(Integer... values) {  
  139.             // 更新进度  
  140.               System.out.println(""+values[0]);  
  141.               message.setText(""+values[0]);  
  142.               pdialog.setProgress(values[0]);  
  143.         }  
  144.   
  145.      }  
  146.   
  147. }  
package cn.test; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.ArrayList; import org.apache.http.HttpEntity; 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; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class NetworkActivity extends Activity{ private TextView message; private Button open; private EditText url; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.network); message= (TextView) findViewById(R.id.message); url= (EditText) findViewById(R.id.url); open= (Button) findViewById(R.id.open); open.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { connect(); } }); } private void connect() { PageTask task = new PageTask(this); task.execute(url.getText().toString()); } class PageTask extends AsyncTask<String, Integer, String> { ProgressDialog pdialog; public PageTask(Context context){ pdialog = new ProgressDialog(context, 0); pdialog.setButton("cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int i) { dialog.cancel(); } }); pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) { finish(); } }); pdialog.setCancelable(true); pdialog.setMax(100); pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pdialog.show(); } //后台运行的方法 ,运行在非ui线程 可以执行耗时的操作 @Override protected String doInBackground(String... params) { try{ HttpClient client = new DefaultHttpClient(); // params[0]代表连接的url HttpGet get = new HttpGet(params[0]); HttpResponse response = client.execute(get); HttpEntity entity = response.getEntity(); long length = entity.getContentLength(); InputStream is = entity.getContent(); String s = null; if(is != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[128]; int ch = -1; int count = 0; while((ch = is.read(buf)) != -1) { baos.write(buf, 0, ch); count += ch; if(length > 0) { // 如果知道响应的长度,调用publishProgress()更新进度 publishProgress((int) ((count / (float) length) * 100)); } // 让线程休眠100ms Thread.sleep(100); } s = new String(baos.toByteArray()); } // 返回结果 return s; } catch(Exception e) { e.printStackTrace(); } return null; } // 运行在主线程中,ui线程中, 在doInbackground执行完毕后执行 @Override protected void onPostExecute(String result) { // 返回HTML页面的内容 message.setText(result); pdialog.dismiss(); } //运行在ui线程中 ,在调用 doInbackground方法之前执行, @Override protected void onPreExecute() { // 任务启动,可以在这里显示一个对话框,这里简单处理 message.setText(R.string.task_started); } //在publishProgress方法被调用后执行 @Override protected void onProgressUpdate(Integer... values) { // 更新进度 System.out.println(""+values[0]); message.setText(""+values[0]); pdialog.setProgress(values[0]); } } } 示例2:下载数据操作

view plain print ?
  1. /** 
  2.  * 下载数据的操作  
  3.  */  
  4. private void fillData() {  
  5.     new AsyncTask<Void, Void, UserEntry>() {  
  6.         // 运行在ui线程中 ,在调用 doInbackground方法之前执行,  
  7.         // 可以做操作ui控件的操作  
  8.         @Override  
  9.         protected void onPreExecute() {  
  10.             super.onPreExecute();  
  11.             //提示用户正在下载数据  
  12.             rl.setVisibility(View.VISIBLE);  
  13.         }  
  14.   
  15.         // 获取实体中的数据,运行在主线程中,ui线程中, 在doInbackground执行完毕后执行  
  16.         @Override  
  17.         protected void onPostExecute(UserEntry ue) {  
  18.             // TODO Auto-generated method stub  
  19.             super.onPostExecute(ue);  
  20.             //隐藏下载数据提示  
  21.             rl.setVisibility(View.INVISIBLE);  
  22.             // 获取用户的名字   
  23.             String title = ue.getTitle().getPlainText();  
  24.             tv_userinfo_title.setText(title);  
  25.             String address = ue.getLocation();  
  26.             tv_userinfo_address.setText(address);  
  27.             String detail =((TextContent) ue.getContent()).getContent().getPlainText();  
  28.             tv_userinfo_detail.setText(detail);  
  29.             String iconpath = ue.getLink("icon"null).getHref();  
  30.             new LoadImageAsynTask(new ImageTaskCallback() {  
  31.                   
  32.                 public void onImageLoaded(Bitmap bitmap) {  
  33.                     if(bitmap!=null){  
  34.                         iv_userinfo_icon.setImageBitmap(bitmap);  
  35.                     }else{  
  36.                         iv_userinfo_icon.setImageResource(R.drawable.ic_launcher);  
  37.                     }  
  38.                 }  
  39.                   
  40.                 public void beforeImageLoaded() {  
  41.                     iv_userinfo_icon.setImageResource(R.drawable.ic_launcher);  
  42.                 }  
  43.             }).execute(iconpath);  
  44.               
  45.         }  
  46.   
  47.         //从网上获取登陆用户的数据实体,后台运行的方法 ,运行在非ui线程 可以执行耗时的操作   
  48.         @Override  
  49.         protected UserEntry doInBackground(Void... params) {  
  50.             try {  
  51.                 UserEntry ue =  myService.getAuthorizedUser();  
  52.                 return ue;  
  53.             } catch (Exception e) {  
  54.                 e.printStackTrace();  
  55.             }   
  56.             return null;  
  57.         }  
  58.     }.execute();  
  59. }  
/** * 下载数据的操作 */ private void fillData() { new AsyncTask<Void, Void, UserEntry>() { // 运行在ui线程中 ,在调用 doInbackground方法之前执行, // 可以做操作ui控件的操作 @Override protected void onPreExecute() { super.onPreExecute(); //提示用户正在下载数据 rl.setVisibility(View.VISIBLE); } // 获取实体中的数据,运行在主线程中,ui线程中, 在doInbackground执行完毕后执行 @Override protected void onPostExecute(UserEntry ue) { // TODO Auto-generated method stub super.onPostExecute(ue); //隐藏下载数据提示 rl.setVisibility(View.INVISIBLE); // 获取用户的名字 String title = ue.getTitle().getPlainText(); tv_userinfo_title.setText(title); String address = ue.getLocation(); tv_userinfo_address.setText(address); String detail =((TextContent) ue.getContent()).getContent().getPlainText(); tv_userinfo_detail.setText(detail); String iconpath = ue.getLink("icon", null).getHref(); new LoadImageAsynTask(new ImageTaskCallback() { public void onImageLoaded(Bitmap bitmap) { if(bitmap!=null){ iv_userinfo_icon.setImageBitmap(bitmap); }else{ iv_userinfo_icon.setImageResource(R.drawable.ic_launcher); } } public void beforeImageLoaded() { iv_userinfo_icon.setImageResource(R.drawable.ic_launcher); } }).execute(iconpath); } //从网上获取登陆用户的数据实体,后台运行的方法 ,运行在非ui线程 可以执行耗时的操作 @Override protected UserEntry doInBackground(Void... params) { try { UserEntry ue = myService.getAuthorizedUser(); return ue; } catch (Exception e) { e.printStackTrace(); } return null; } }.execute(); }

你可能感兴趣的:(Android之AsyncTask的用法)