`
caiwb1990
  • 浏览: 316175 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android异步4:深入AsyncTask原理

阅读更多
AsyncTask的本质是一个线程池,所有提交的异步任务都会在这个线程池(想想C3P0)中的工作线程内执行,当工作线程需要跟UI线程交互时,工作线程会通过向在UI线程创建的Handler传递消息的方式,调用相关的回调函数,从而实现UI界面的更新。

还是以昨天的例子为例~来说明AsyncTask的实现原理
    package cn.caiwb.aysnc;  
      
      
    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.graphics.Bitmap;  
    import android.graphics.BitmapFactory;  
    import android.os.AsyncTask;  
    import android.os.Bundle;  
    import android.view.View;  
    import android.view.View.OnClickListener;  
    import android.widget.Button;  
    import android.widget.ImageView;  
    import android.widget.ProgressBar;  
    import android.widget.Toast;  
      
    public class AsyncTaskActivity extends Activity {  
          
        private ImageView mImageView;  
        private Button mButton;  
        private ProgressBar mProgressBar;  
          
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main);  
              
            mImageView= (ImageView) findViewById(R.id.imageView);  
            mButton = (Button) findViewById(R.id.button);  
            mProgressBar = (ProgressBar) findViewById(R.id.progressBar);  
            mButton.setOnClickListener(new OnClickListener() {  
                  
                @Override  
                public void onClick(View v) {  
                    GetIteyeLogoTask task = new GetIteyeLogoTask();  
                    task.execute("http://www.iteye.com/images/logo.gif");  
                }  
            });  
        }  
          
        class GetIteyeLogoTask extends AsyncTask<String,Integer,Bitmap> {//继承AsyncTask  
      
            @Override  
            protected Bitmap doInBackground(String... params) {//处理后台执行的任务,在后台线程执行  
                publishProgress(0);//将会调用onProgressUpdate(Integer... progress)方法  
                HttpClient hc = new DefaultHttpClient();  
                publishProgress(30);  
                HttpGet hg = new HttpGet(params[0]);//获取csdn的logo  
                final Bitmap bm;  
                try {  
                    HttpResponse hr = hc.execute(hg);  
                    bm = BitmapFactory.decodeStream(hr.getEntity().getContent());  
                } catch (Exception e) {  
                      
                    return null;  
                }  
                publishProgress(100);  
                //mImageView.setImageBitmap(result); 不能在后台线程操作ui  
                return bm;  
            }  
              
            protected void onProgressUpdate(Integer... progress) {//在调用publishProgress之后被调用,在ui线程执行  
                mProgressBar.setProgress(progress[0]);//更新进度条的进度  
             }  
      
             protected void onPostExecute(Bitmap result) {//后台任务执行完之后被调用,在ui线程执行  
                 if(result != null) {  
                     Toast.makeText(AsyncTaskActivity.this, "成功获取图片", Toast.LENGTH_LONG).show();  
                     mImageView.setImageBitmap(result);  
                 }else {  
                     Toast.makeText(AsyncTaskActivity.this, "获取图片失败", Toast.LENGTH_LONG).show();  
                 }  
             }  
               
             protected void onPreExecute () {//在 doInBackground(Params...)之前被调用,在ui线程执行  
                 mImageView.setImageBitmap(null);  
                 mProgressBar.setProgress(0);//进度条复位  
             }  
               
             protected void onCancelled () {//在ui线程执行  
                 mProgressBar.setProgress(0);//进度条复位  
             }  
              
        }  
          
      
    }  


分析:

在分析实现流程之前,我们先了解一下AsyncTask有哪些成员变量。

   private static final int CORE_POOL_SIZE =5;//5个核心工作线程
   private static final int MAXIMUM_POOL_SIZE = 128;//最多128个工作线程
   private static final int KEEP_ALIVE = 1;//空闲线程的超时时间为1秒
 
   private static final BlockingQueue<Runnable> sWorkQueue =
           new LinkedBlockingQueue<Runnable>(10);//等待队列
 
   private static final ThreadPoolExecutorsExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
           MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue,sThreadFactory);//线程池是静态变量,所有的异步任务都会放到这个线程池的工作线程内执行。



回到例子中,点击按钮之后会新建一个GetIteyeLogoTask对象:

GetIteyeLogoTask task = new GetIteyeLogoTask();  


此时会调用父类AsyncTask的构造函数:

AsyncTask.java

public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                return doInBackground(mParams);
            }
        };

        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                Message message;
                Result result = null;

                try {
                    result = get();
                } catch (InterruptedException e) {
                    android.util.Log.w(LOG_TAG, e);
                } catch (ExecutionException e) {
                    throw new RuntimeException("An error occured while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
                            new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
                    message.sendToTarget();//取消任务,发送MESSAGE_POST_CANCEL消息
                    return;
                } catch (Throwable t) {
                    throw new RuntimeException("An error occured while executing "
                            + "doInBackground()", t);
                }

                message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                        new AsyncTaskResult<Result>(AsyncTask.this, result));//完成任务,发送MESSAGE_POST_RESULT消息并传递result对象
                message.sendToTarget();
            }
        };
    }



WorkerRunnable类实现了callable接口的call()方法,该函数会调用我们在AsyncTask子类中实现的doInBackground(mParams)方法,由此可见,WorkerRunnable封装了我们要执行的异步任务。FutureTask中的protected void done() {}方法实现了异步任务状态改变后的操作。当异步任务被取消,会向UI线程传递MESSAGE_POST_CANCEL消息,当任务成功执行,会向UI线程传递MESSAGE_POST_RESULT消息,并把执行结果传递到UI线程。

由此可知,AsyncTask在构造的时候已经定义好要异步执行的方法doInBackground(mParams)和任务状态变化后的操作(包括失败和成功)。

当创建完GetIteyeLogoTask对象后,执行

task.execute("http://www.iteye.com/images/logo.gif");  


此时会调用AsyncTask的execute(Params...params)方法

public final AsyncTask<Params,Progress, Result> execute(Params... params) {
        if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    throw newIllegalStateException("Cannot execute task:"
                            + " the taskis already running.");
                case FINISHED:
                    throw newIllegalStateException("Cannot execute task:"
                            + " the taskhas already been executed "
                            + "(a task canbe executed only once)");
            }
        }
 
        mStatus = Status.RUNNING;
 
        onPreExecute();//运行在ui线程,在提交任务到线程池之前执行
 
        mWorker.mParams = params;
        sExecutor.execute(mFuture);//提交任务到线程池
 
        return this;
}


当任务正在执行或者已经完成,会抛出IllegalStateException,由此可知我们不能够重复调用execute(Params...params)方法。在提交任务到线程池之前,调用了onPreExecute()方法。然后才执行sExecutor.execute(mFuture)是任务提交到线程池。

前面我们说到,当任务的状态发生改变时(1、执行成功2、取消执行3、进度更新),工作线程会向UI线程的Handler传递消息。我们知道Handler要处理其他线程传递过来的消息。在AsyncTask中,InternalHandler是在UI线程上创建的,它接收来自工作线程的消息,实现代码如下:

private static class InternalHandler extends Handler {
       @SuppressWarnings({"unchecked","RawUseOfParameterizedType"})
        @Override
        public voidhandleMessage(Message msg) {
            AsyncTaskResult result =(AsyncTaskResult) msg.obj;
            switch (msg.what) {
                caseMESSAGE_POST_RESULT:
                    // There is onlyone result
                    result.mTask.finish(result.mData[0]);//执行任务成功
                    break;
                caseMESSAGE_POST_PROGRESS:
                   result.mTask.onProgressUpdate(result.mData);//进度更新
                    break;
                caseMESSAGE_POST_CANCEL:
                    result.mTask.onCancelled();//取消任务
                    break;
            }
        }
    }


当接收到消息之后,AsyncTask会调用自身相应的回调方法。

总结:

1、 AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。

2、线程池中的工作线程执行doInBackground(mParams)方法执行异步任务

3、当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数


1
2
分享到:
评论

相关推荐

    Android用AsyncTask异步加载图片(新)

    本篇文章将深入探讨如何在Android中使用`AsyncTask`来异步加载网络图片。 首先,我们了解`AsyncTask`的基本结构。`AsyncTask`有三个泛型参数:`Params`, `Progress`, 和 `Result`。在本例中,`Params`通常是网络...

    异步任务AsyncTask

    让我们深入了解一下`AsyncTask`及其工作原理。 ### 1. AsyncTask简介 `AsyncTask`是Android提供的一个轻量级组件,用于在后台线程执行任务,然后在UI线程更新结果。它包含三个泛型参数:`Params`、`Progress`和`...

    android较轻级异步任务AsyncTask

    本文将深入探讨`AsyncTask`的工作原理、使用方法以及注意事项。 ### 1. `AsyncTask`概述 `AsyncTask`是Android SDK中的一个抽象类,它允许开发者在后台线程中执行任务,并在UI线程中更新结果。它的设计目标是简化...

    Android AsyncTask 源码解析

    通过以上对 AsyncTask 的源码解析和使用方法的介绍,你应该对如何在 Android 应用中高效地使用异步任务有了更深入的理解。在实际开发中,正确理解和使用 AsyncTask 可以帮助我们编写出更加流畅、响应快速的应用程序...

    Android-详细解读AsyncTask的黑暗面以及一种替代方案

    在深入探讨AsyncTask的“黑暗面”之前,我们先来回顾一下AsyncTask的基本用法和工作原理。 AsyncTask主要由四个关键部分组成:onPreExecute()、doInBackground()、onProgressUpdate()和onPostExecute()。其中,...

    Android开发之AsyncTask机制及使用细节例子源码

    在Android应用开发中,异步任务(AsyncTask)是一个常用工具,用于在后台线程执行耗时操作,然后在UI线程更新结果,避免阻塞用户界面。AsyncTask的使用和内部机制对于任何Android开发者来说都至关重要。让我们深入...

    Android异步任务完整实例

    下面将详细解释Android异步任务的概念、工作原理以及如何在实际项目中应用。 一、Android异步任务概述 Android系统为了解决在主线程(UI线程)中执行耗时操作导致的应用程序无响应(ANR)问题,引入了异步任务。...

    android异步任务框架源码

    本文将深入探讨“android异步任务框架源码”,讲解其核心概念、工作原理以及如何实现。 Android中的异步任务通常通过AsyncTask类来实现。AsyncTask是一个轻量级的组件,设计用于在UI线程和后台线程之间进行通信。它...

    异步操作类AsyncTask

    对于深入理解Android的多线程编程,`AsyncTask`是一个重要的起点,但随着Android版本的更新,建议开发者了解并掌握更现代的异步处理技术,如`Coroutines`和`ViewModel`配合`LiveData`,以获得更好的性能和可维护性。...

    android任务后台处理 asyncTask封装

    下面我们将深入探讨`AsyncTask`的工作原理及其封装方法。 `AsyncTask`的核心在于三个泛型参数:`Params`、`Progress`和`Result`,它们分别代表了后台任务的输入参数类型、后台执行过程中的进度类型和任务执行结果的...

    Android AsyncTask(异步) 简单样例

    本篇文章将深入探讨Android AsyncTask的工作原理、使用方法以及一些常见应用场景。 **一、Android AsyncTask概述** AsyncTask是Android提供的一个类,它允许开发者在后台线程执行任务,然后在UI线程更新结果,以...

    android AsyncTask详细介绍

    本文将深入探讨Android的AsyncTask及其与Handler的对比。 **AsyncTask详解** AsyncTask是Android SDK提供的一种轻量级的异步处理机制,特别适合于执行短时间的、与UI相关的后台任务。它的主要优点在于简化了UI更新...

    Android开发笔记之:深入理解多线程AsyncTask

    本篇文章将深入探讨`AsyncTask`的工作原理和如何在实际应用中使用。 首先,`AsyncTask`是自Android 1.5版本起引入的,主要为了解决在Android平台上进行异步操作的问题。它通过提供一个简单的接口,允许开发者在后台...

    android asyncTask

    这篇博文将深入探讨`AsyncTask`的工作原理及其在实际开发中的应用。 `AsyncTask`类提供了三个泛型参数:`Params`、`Progress`和`Result`。`Params`代表执行任务所需的输入参数类型,`Progress`表示后台任务执行过程...

    一个AsyncTask异步任务的操作实例

    在这个“一个AsyncTask异步任务的操作实例”中,我们将深入探讨AsyncTask的工作原理、使用方法以及如何在实际项目中应用。 1. **AsyncTask基本结构**: AsyncTask由三个泛型参数定义:`Params`, `Progress`, 和 `...

    Android 异步加载解决方案

    本文将深入探讨Android的异步加载解决方案,尤其是通过`AsyncTask`类实现的方式。 `AsyncTask`是Android SDK提供的一种轻量级的异步处理工具,适用于快速执行少量的后台任务。它具有三个泛型参数:`Params`(输入...

    Android的异步任务AsyncTask详解

    在本文中,我们将深入探讨AsyncTask的原理、使用方法以及其限制。 AsyncTask的定义: 正如官方文档所述,AsyncTask是为了方便在UI线程和后台线程之间进行交互而设计的。它允许开发者在后台执行操作,并在完成后更新...

    安卓拍照上传录像监控录屏相关-android录音上传到服务器上传使用AsyncTask异步任务.rar

    下面,我们将深入探讨Android系统中的这些功能及其与AsyncTask的结合使用。 1. **拍照上传**: 在Android中,拍照通常通过调用`Intent`来启动系统相机应用完成。一旦用户拍摄照片,应用可以通过`onActivityResult...

    异步AsyncTask状态监控

    本教程将深入讲解AsyncTask的工作原理、如何创建和使用,以及如何实现对异步任务状态的监控,特别是关注任务的结束状态。 AsyncTask的核心理念是“后台计算,前台显示”,它提供了三个泛型参数:Params, Progress, ...

Global site tag (gtag.js) - Google Analytics