在实际应用中经常会遇到比较耗时任务的处理,比如网络连接,数据库操作等情况时,如果这些操作都是放在主线程(UI线程)中,则会造成UI的假死现象,Android中可以使用AsyncTask和Handler两种异步方式来解决这种问题。

AsyncTask:

android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.
使用的优点:
简单,快捷,过程可控
使用的缺点:
在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.

在使用AsyncTask时处理类需要继承AsyncTask,提供三个泛型参数,并且重载AsyncTask的四个方法(至少重载一个)。

三个泛型参数:
1.Param 任务执行器需要的数据类型
2.Progress 后台计算中使用的进度单位数据类型
3.Result 后台计算返回结果的数据类型
在设置参数时通常是这样的:String... params,这表示方法可以有0个或多个此类型参数;有时参数可以设置为不使用,用Void...即可。

四个方法:
1.onPreExecute()执行预处理,它运行于UI线程,可以为后台任务做一些准备工作,比如绘制一个进度条控件。
2.doInBackground(Params...)后台进程执行的具体计算在这里实现,doInBackground(Params...)是AsyncTask的关键,此方法必须重载。在这个方法内可以使用publishProgress(Progress...)改变当前的进度值。
3.onProgressUpdate(Progress...)运行于UI线程。如果在doInBackground(Params...) 中使用了publishProgress(Progress...),就会触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。
4.onPostExecute(Result)运行于UI线程,可以对后台任务的结果做出处理,结果就是doInBackground(Params...)的返回值。此方法也要经常重载,如果Result为null表明后台任务没有完成(被取消或者出现异常)。

异步任务类代码:

[java] view plain copy print ?
  1. //AsyncTask异步方式下载图片
  2. classDownImageTaskextendsAsyncTask<String,Integer,Bitmap>{
  3. //执行预处理
  4. @Override
  5. protectedvoidonPreExecute(){
  6. super.onPreExecute();
  7. //显示进度条
  8. progressBar.setVisibility(View.VISIBLE);
  9. progressBar.setMax(100);
  10. }
  11. //后台进程的执行
  12. @Override
  13. protectedBitmapdoInBackground(String...params){
  14. try{
  15. URLurl=newURL(params[0]);
  16. HttpURLConnectionconn=(HttpURLConnection)url
  17. .openConnection();
  18. InputStreaminputStream=conn.getInputStream();
  19. bitmap=BitmapFactory.decodeStream(inputStream);
  20. //进度条的更新,我这边只是用一个循环来示范,在实际应用中要使用已下载文件的大小和文件总大小的比例来更新
  21. for(inti=1;i<=10;i++){
  22. publishProgress(i*10);
  23. Thread.sleep(200);
  24. }
  25. inputStream.close();
  26. }catch(Exceptione){
  27. e.printStackTrace();
  28. }
  29. returnbitmap;
  30. }
  31. //运行于UI线程,对后台任务的结果做出处理,doInBackground方法执行的结果作为此方法的参数
  32. @Override
  33. protectedvoidonPostExecute(Bitmapresult){
  34. super.onPostExecute(result);
  35. ImageViewimageView=(ImageView)findViewById(R.id.image);
  36. imageView.setImageBitmap(result);
  37. progressBar.setVisibility(View.GONE);
  38. }
  39. //运行于UI线程,如果在doInBackground(Params...)中使用了publishProgress(Progress...),就会触发此方法
  40. @Override
  41. protectedvoidonProgressUpdate(Integer...values){
  42. super.onProgressUpdate(values);
  43. progressBar.setProgress(values[0]);
  44. }
  45. }
// AsyncTask异步方式下载图片class DownImageTask extends AsyncTask<String, Integer, Bitmap> {// 执行预处理@Overrideprotected void onPreExecute() {super.onPreExecute();// 显示进度条progressBar.setVisibility(View.VISIBLE);progressBar.setMax(100);}// 后台进程的执行@Overrideprotected Bitmap doInBackground(String... params) {try {URL url = new URL(params[0]);HttpURLConnection conn = (HttpURLConnection) url.openConnection();InputStream inputStream = conn.getInputStream();bitmap = BitmapFactory.decodeStream(inputStream);// 进度条的更新,我这边只是用一个循环来示范,在实际应用中要使用已下载文件的大小和文件总大小的比例来更新for (int i = 1; i <= 10; i++) {publishProgress(i * 10);Thread.sleep(200);}inputStream.close();} catch (Exception e) {e.printStackTrace();}return bitmap;}// 运行于UI线程,对后台任务的结果做出处理,doInBackground方法执行的结果作为此方法的参数@Overrideprotected void onPostExecute(Bitmap result) {super.onPostExecute(result);ImageView imageView = (ImageView) findViewById(R.id.image);imageView.setImageBitmap(result);progressBar.setVisibility(View.GONE);}// 运行于UI线程,如果在doInBackground(Params...)中使用了publishProgress(Progress...),就会触发此方法@Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);progressBar.setProgress(values[0]);}}

调用代码:

[java] view plain copy print ?
  1. publicclassMainActivityextendsActivity{
  2. privateButtonbutton;
  3. privateProgressBarprogressBar;
  4. @Override
  5. publicvoidonCreate(BundlesavedInstanceState){
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.main);
  8. button=(Button)findViewById(R.id.button);
  9. progressBar=(ProgressBar)findViewById(R.id.progressBar);
  10. button.setOnClickListener(newOnClickListener(){
  11. @Override
  12. publicvoidonClick(Viewv){
  13. ProgressBarAsyncTaskasyncTask=newDownImageTask();
  14. asyncTask.execute("http://www.baidu.com/img/baidu_jgylogo3.gif");
  15. }
  16. });
  17. }
public class MainActivity extends Activity {      private Button button;    private ProgressBar progressBar;           @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.main);                    button = (Button)findViewById(R.id.button);        progressBar = (ProgressBar)findViewById(R.id.progressBar);                  button.setOnClickListener(new OnClickListener() {                            @Override              public void onClick(View v) {                  ProgressBarAsyncTask asyncTask = new DownImageTask();                  asyncTask.execute("http://www.baidu.com/img/baidu_jgylogo3.gif");            }          });    }

Handler:
Handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程中)
两个作用:
安排消息或Runnable 在某个主线程中某个地方执行
安排一个动作在不同的线程中执行

Handler中分发消息的方法:
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable,long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
*以上post开头的方法在主线程中调用。
*以上send开头的方法在其它线程中调用。

示例代码:

[java] view plain copy print ?
  1. publicclassHandlerTestActivityextendsActivity{
  2. privateButtonstart;
  3. @Override
  4. protectedvoidonCreate(BundlesavedInstanceState){
  5. //TODOAuto-generatedmethodstub
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.handlertest);
  8. start=(Button)findViewById(R.id.start);
  9. start.setOnClickListener(newstartListener());
  10. System.out.println("ActivityThread:"+Thread.currentThread().getId());
  11. }
  12. Handlerhandler=newHandler(){
  13. @Override
  14. publicvoidhandleMessage(Messagemsg){
  15. //TODOAuto-generatedmethodstub
  16. if(msg.what==1){
  17. //成功,做一些操作
  18. }else{
  19. //失败,..
  20. }
  21. }
  22. };
  23. Runnablethread=newRunnable(){
  24. @Override
  25. publicvoidrun(){
  26. //TODOAuto-generatedmethodstub
  27. System.out.println("HandlerThread:"+Thread.currentThread().getId());
  28. //Messagemessage=newMessage();
  29. //message.what=1;
  30. //handler.sendMessage(message);
  31. }
  32. };
  33. classstartListenerimplementsOnClickListener{
  34. @Override
  35. publicvoidonClick(Viewv){
  36. //TODOAuto-generatedmethodstub
  37. handler.post(thread);
  38. //Threadt=newThread(thread);
  39. //t.start();
  40. }
  41. }
  42. }
public class HandlerTestActivity extends Activity {    private Button start;    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub         super.onCreate(savedInstanceState);        setContentView(R.layout.handlertest);        start = (Button) findViewById(R.id.start);        start.setOnClickListener(new startListener());        System.out.println("Activity Thread:" + Thread.currentThread().getId());    }    Handler  handler = new Handler(){        @Override        public void handleMessage(Message msg) {            // TODO Auto-generated method stub            if (msg.what == 1) {                //成功,做一些操作            } else {                //失败,..            }        }            };    Runnable thread  = new Runnable() {                         @Override                         public void run() {                             // TODO Auto-generated method stub                              System.out.println("HandlerThread:" + Thread.currentThread().getId());                             //Message message = new Message();                             //message.what = 1;                             //handler.sendMessage(message);                         }                     };    class startListener implements OnClickListener {        @Override        public void onClick(View v) {            // TODO Auto-generated method stub             handler.post(thread);            //Thread t = new Thread(thread);            //t.start();        }    }}


这个程序看上去似乎实现了Handler的异步机制, handler.post(thread)似乎实现了新启线程的作用,不过通过执行我们发现,两个线程的ID相同!也就是说,实际上thread还是原来 的主线程,由此可见,handler.post()方法并未真正新建线程,只是在原线程上执行而已,我们并未实现异步机制。将startListener改写成如下代码就可以实现异步:

[java] view plain copy print ?
  1. classstartListenerimplementsOnClickListener{
  2. @Override
  3. publicvoidonClick(Viewv){
  4. //TODOAuto-generatedmethodstub
  5. //handler.post(thread);
  6. Threadt=newThread(thread);
  7. t.start();
  8. }
  9. }
class startListener implements OnClickListener {        @Override        public void onClick(View v) {            // TODO Auto-generated method stub             //handler.post(thread);            Thread t = new Thread(thread);            t.start();        }    }

将runnable放到新创建的线程中执行,这样就实现了异步调用,如果需要在调用完成后通知或修改主线程,需要在Runnable类的run方法中调用handler.sendMessage(message)

[java] view plain copy print ?
  1. @Override
  2. publicvoidrun(){
  3. //TODOAuto-generatedmethodstub
  4. System.out.println("HandlerThread:"+Thread.currentThread().getId());
  5. Messagemessage=newMessage();
  6. message.what=1;
  7. handler.sendMessage(message);
  8. }
@Override public void run() {     // TODO Auto-generated method stub      System.out.println("HandlerThread:" + Thread.currentThread().getId());     Message message = new Message();     message.what = 1;     handler.sendMessage(message);}


更多相关文章

  1. Android(安卓)Service生命周期及用法!
  2. Android的SQLite学习及使用方法(1)
  3. Android的Handler总结
  4. Android的UI设计与后台线程交互
  5. Android(安卓)之 Looper Handler Message 之间的关系
  6. Android(安卓)面试大全
  7. Android自适应不同屏幕几种方法
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. android 自定义dialog,窗口动画,
  2. Android Path的使用详解
  3. Android SHA1加密实现
  4. 分享一些Android免费课程给大家
  5. android ksoap2下webservice的 https请求
  6. ANDROID取CPU序列号
  7. Android实现水印效果
  8. Android之Activity的几种跳转方式
  9. Android跳转淘宝商品详情页代码
  10. Android 开源项目地址备份(持续更新。。。