`

AsyncTask的源码分析 与 使用 之我的浅解

 
阅读更多

由于主线程负责处理用户输入事件, 如果主线程被阻塞,应用就会报ANR错误.为了不阻塞主线程,我们需要在子线程中处理耗时的操作,在处理耗时操作的过程中,子线程可能需要更新UI控件的显示, 由于UI控件的更新重绘是由主线程负责的,所以子线程需要通过Handler发送消息到主线程的消息对列中, 由运行在主线程的消息处理代码接收到消息后更新UI控件的显示.

采用线程+Handler实现异步处理时,当每次执行耗时操作都创建一条新线程进行处理,性能开销会比较大, 如果耗时操作执行的时间比较长,就有可能同时运行着许多线程,系统终将不堪重负. 为了提高性能我们使用AsyncTask实现异步处理,事实上其内部也是采用线程+handler来实现异步处理的.只不过是其内部使用了JDK5提供的线程池技术,有效的降低了线程创建数量及限定了同时运行的线程数,还有一些针对性的对池的优化操作.

AsyncTask内部使用了JDK5后的线程池ThreadPoolExecutor,在内部自定义配置了AsyncTask的专用线程池sExecutor执行者。而这种线程池的配置需要对系统和业务的理解来定的.我们一般默认最好,而JDK也建议我们使用它提供的几个已经封装好的类.

还是先看一看关于AsyncTask的代码

public abstract class AsyncTask<Params, Progress, Result> {
    private static final String LOG_TAG = "AsyncTask";
    //核心线程数5;
    private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;//最大线程数128
// 当线程数大于核心时,终止当前多余的空闲线程等待新任务的最长时间10(单位未知)
private static final int KEEP_ALIVE = 10; 
//创建10容量的基于已链接节点的、范围任意的 blocking queue。此队列按 FIFO(先进先出)排序元素
    private static final BlockingQueue<Runnable> sWorkQueue =
            new LinkedBlockingQueue<Runnable>(10);
//定制内部线程池的生成线程的简单工厂,并为每个任务指定 了一个递增的唯一的id
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };
/**
 * 创建线程池(看配置好像是文档中所说的小队列较大池policy)
 */
    private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
            MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);

    private static final int MESSAGE_POST_RESULT = 0x1;
    private static final int MESSAGE_POST_PROGRESS = 0x2;
    private static final int MESSAGE_POST_CANCEL = 0x3;
   //又在内部准备了一个处理器(由于这个AsyncTask在UI线程中使用,所以这个InternalHandler是主线程的啦)
    private static final InternalHandler sHandler = new InternalHandler();
   //工作任务封装类
    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;
   //volatile类型的枚举值, 默认表示为PENDING未执行状态
    private volatile Status mStatus = Status.PENDING;

    /**
     * Indicates the current status of the task. Each status will be set only once
     * during the lifetime of a task.
     */
    public enum Status {
        /**
         * Indicates that the task has not been executed yet.
         */
        PENDING,
        /**
         * Indicates that the task is running.
         */
        RUNNING,
        /**
         * Indicates that {@link AsyncTask#onPostExecute} has finished.
         */
        FINISHED,
    }
//构造方法

/**
     * Creates a new asynchronous task
* This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                //设置任务执行的优先级比默认线程优先级略低一些
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                return doInBackground(mParams); //回调doInBackGround(数组)方法
            }
        };
        //用mWorker创建一个可取消的异步计算任务
        mFuture = new FutureTask<Result>(mWorker) {
            //当任务不管是正常终止、异常或取消而完成的,都回调此方法, 即isDone()为true时
            @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) {
                    //当发生CancellationException异常时说明任务被取消了, 消息通知UI线程
                    message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
                            new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
                    message.sendToTarget();
                    return;
                } catch (Throwable t) {
                    throw new RuntimeException("An error occured while executing "
                            + "doInBackground()", t);
                }
                //正常结束任务后发消息执行MESSAGE_POST_RESULT的回调操作
                message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                        new AsyncTaskResult<Result>(AsyncTask.this, result));
                message.sendToTarget();
            }
        };
    }



public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
            ExecutionException, TimeoutException {
        return mFuture.get(timeout, unit);
    }


//这是AsyncTask异步任务的启动方法
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        //首先判断AsyncTask异步任务的状态,当处于RUNNING和FINISHED时就报IllegalStateException非法状态异常
if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
            }
        }

        mStatus = Status.RUNNING;

        onPreExecute();

        mWorker.mParams = params;
        sExecutor.execute(mFuture);

        return this;
    }


protected final void publishProgress(Progress... values) {
        sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }

    private void finish(Result result) {
        if (isCancelled()) result = null;
        onPostExecute(result);
        mStatus = Status.FINISHED;
    }
    //这个就是它的内部回调机制的回调方法处理
    private static class InternalHandler extends Handler {
        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // There is only one result
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
                case MESSAGE_POST_CANCEL:
                    result.mTask.onCancelled();
                    break;
            }
        }
    }

    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }
     //对结果的封装
    @SuppressWarnings({"RawUseOfParameterizedType"})
    private static class AsyncTaskResult<Data> {
        final AsyncTask mTask;
        final Data[] mData;

        AsyncTaskResult(AsyncTask task, Data... data) {
            mTask = task;
            mData = data;
        }
    }

好了这就是AsyncTask的全部代码,里面省略了部分回调和基本的获取任务信息的代码,而这此也都是对JDK5并发库中类的封装使用,有兴趣的可以看看,这里不做过多解释.

首先来理一下AsyncTask的执行过程.

1, 首先我们一般先在主线程中创建一个AsyncTask类的匿名内部类, 并指明它的三个范型的参数化类型.

而在其构造方法中做了一件事,准备了一个将要执行的可取消的任务赋值给mFuture,

首先实现了WorkerRunnable 抽象类mWorker,并在其call执行方法中回调在后台执行的doInBackground()方法并params预设给这个方法.

然后用这个mWorker准备创建new FutureTask<Result>(mWorker)并在其done()方法中用result =get();等待执行的结果,当这个后台执行的FutureTask被取消后并捕获到CancellationException异常就用InternalHandler类型的sHandler向主线程发送标志为MESSAGE_POST_CANCEL|结果为Null的消息.而任务被正常执行完成后向主线程发送MESSAGE_POST_RESULT|结果为result的消息.

2, 在匿名内部类中我们重写四个onPostExecute, onPreExecute, onProgressUpdate, onCancelled

在主线程执行的方法, 和 一个doInBackground实际后台工作的方法

3, 当我们做完这一切后,调用execute(params)首先设置状态sStataus为Status.RUNNING,执行onPreExecute();回调,然后将params赋值给WorkerRunnable的params数组最后将构造中准备好的mFuture交给线程池中执行.

4. 剩下的事就是在done中等待执行结果.然后向主线程发送消息.而处理器已经准备了三种消息类别分别对应了不同的响应:

1) MESSAGE_POST_RESULT:onPostExecute(result);

2) MESSAGE_POST_PROGRESS: onProgressUpdate(result.mData);

3) MESSAGE_POST_CANCEL: onCancelled()

还有一个问题我注意到MESSAGE_POST_PROGRESS我看到是在publishProgress方法中发送的.

protected final void publishProgress(Progress... values) {

sHandler.obtainMessage(MESSAGE_POST_PROGRESS,

newAsyncTaskResult<Progress>(this, values)).sendToTarget();

}

而在AsyncTask类内部并没有对这个publishProgress方法的调用而这个方法又是protected的,通过查看文档这个方法的最佳调用时机是在doInBackground方法中向UI主线程publish updates,

另外也必须强调的是AsyncTask这个抽象类内部只用一个protected abstract Result doInBackground(Params... params);的抽象方法,在实现这个类的时候是必须要准备好这个后台执行的方法,其他可选.

写到这也差不多了,

再向大家介绍我对AsyncTask类的简单封装使用方法(当在应用中多处使用同样的异步任务时可以考虑)

首先把这个异步任务类独立出来,并类的构造中指定自定义的接口实现

public class MyAsyncTask extends AsyncTask <Params, Progress, Result>{
	
	private ResponseInterface response;
	public MyAsyncTask (ResponseInterface response) {
		this.response = response;
	}
	/**
	 * 对asyncTask任务的简单封装的接口,
	 * 在使用此任务时主线程的工作就放在这个接口方法中实现
	 * 后台任务交给该任务的doInBackground
	 */
	public interface ResponseInterface{
		void preRunning();
		void finished(Result result);
	}
	/**
	 * 任务执行前
	 */
	@Override
	protected void onPreExecute() {
		response. preRunning ();
		super.onPreExecute();
	}
	/**
	 * 任务执行后
	 */
	@Override
	protected void onPostExecute(Result result) {
		if(null != result){
			response. finished (result);
		}
		super.onPostExecute(result);
	}

	@Override
	protected Boolean doInBackground(Params... params) {
		//doSomething();
		return true;
	}
 
	/**
	 * 任务执行进度更新
	 */
	@Override
	protected void onProgressUpdate(Progress... values) {

		super.onProgressUpdate(values);
	}

	/**
	 * 任务完取消后执行
	 */
	@Override
	protected void onCancelled() {
		
		super.onCancelled();
	}
}

这样的话后台执行的业务逻辑与前台UI的执行就分离出来的,在使用时只要new出这个AsyncTask异步任务类并指定这个内部接口的实现类就可以了,在前台只做前台的事,后台则交给这个自定义的AsyncTask异步任务类来实现.




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics