AsyncTask源码解析

关于AsyncTask的使用可以参看android sdk提供的AsyncTask相关文档,本文来解析AsyncTask的源代码。

我们只需要调用AsyncTask的execute方法,因此我们也将从这里开始。

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        if (mStatus != Status.PENDING) {//Status有PENDING(未执行),RUNNING(正在执行),FINISHED(已完成)三个状态,如果mStatus不为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;//从PENDING状态转为RUNNING,所以当AsyncTask只能调用一次execute,第二次调用时mStatus为RUNNING就会抛出异常

        onPreExecute();//由UI线程在执行doInBackground方法之前执行

        mWorker.mParams = params;//mWorker为WorkerRunnable类型,WorkerRunnable是AsyncTask的一个抽象静态内部类,该类继承了Callable接口,并且拥有Params[] mParams做为其成员
        sExecutor.execute(mFuture);//mFuture为FutureTask类型,该类实现Future<V>, Runnable接口,sExecutor是一个ThreadPoolExecutor类型

        return this;
    }
当执行sExecutor.execute(mFuture)时,调用了ThreadPoolExecutor中的execute方法,该方法使用一个Runnable作为参数,如下:

public void execute(Runnable command) {
	     ......
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
          ......
    }
其中addWorker方法会把传进来的Runnable对象放入其工作队列中,并执行该Runnable,如下:

private boolean addWorker(Runnable firstTask, boolean core) {
		.....
        Worker w = new Worker(firstTask);
        Thread t = w.thread;
        final ReentrantLock mainLock = this.mainLock;//获得线程锁
        mainLock.lock();//锁住线程
        try {
            int c = ctl.get();
            int rs = runStateOf(c);

            if (t == null ||
                (rs >= SHUTDOWN &&
                 ! (rs == SHUTDOWN &&
                    firstTask == null))) {
                decrementWorkerCount();
                tryTerminate();
                return false;
            }

            workers.add(w);//放入工作队列

            int s = workers.size();
            if (s > largestPoolSize)
                largestPoolSize = s;
        } finally {
            mainLock.unlock();//开锁
        }

        t.start();//执行线程,关键
        ...
        return true;
    }
到此我们知道AsyncTask的execute的执行流程为
先调用ThreadPoolExecutor.execute(mFuture);
然后ThreadPoolExecutor.execute(mFuture) 会调用ThreadPoolExecutor.addWorker(mFuture);
最后ThreadPoolExecutor.addWorker(mFuture)会调用mFuture的run()方法,run方法中就是该线程要执行操作的地方
到此我们来关注一下mFuture,AsyncTask中的mFuture是一个FutureTask,FutureTask实现了Future<V>, Runnable两个接口,
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果,计算完成后只能使用 get 方法来获取结果。
mFuture以mWorker作为参数
 mFuture = new FutureTask<Result>(mWorker) {
	 。。。。
}

用到了FutureTask的一个构造函数

public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        sync = new Sync(callable);
    }
sync为Sync类,Sync类为FutureTask的内部类,该类是AbstractQueuedSynchronizer类的子类

private final class Sync extends AbstractQueuedSynchronizer{
	...
}
因此我们知道mWorker是一个实现了callable接口的类,并且持有Params[] mParams参数
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
   Params[] mParams;
}
我们再来看看FutureTask的run方法
   public void run() {
        sync.innerRun();
    }
调用了sync的innerRun()方法。

void innerRun() {
	...
		runner = Thread.currentThread();
		if (getState() == RUNNING) { // recheck after setting thread
			V result;
			try {
				result = callable.call();//调用callable的call方法并返回值,此时的callable为mWorker
			} catch (Throwable ex) {
				setException(ex);
				return;
			}
			set(result);//设置结果
		} else {
			releaseShared(0); // cancel
		}
	}
innerRun方法中调用了callable的call方法,该callable在这里就是mWorker,我们来看看mWorker的call方法

mWorker = new WorkerRunnable<Params, Result>() {
	public Result call() throws Exception {
		Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
		return doInBackground(mParams);
	}
};
先设置线程级别为THREAD_PRIORITY_BACKGROUND(10),Linux线程级别从-20(最高)~19(最低),普通级别值为0,因而THREAD_PRIORITY_BACKGROUND级别比普通级别低
然后执行AsyncTask的doInBackground方法,并返回结果。所以当我们把耗时的工作量放在doInBackground方法里执行时,实际上是把大工作量放到了一个低级别的线程中去执行。

FutureTask中的run方法调用完callable.call()并获得结果之后就会调用set(result)方法,我们来看看set方法

protected void set(V v) {
	sync.innerSet(v);
}
调用sync的innerSet方法:

void innerSet(V v) {
		for (;;) {
			...
			if (compareAndSetState(s, RAN)) {
				result = v;
				releaseShared(0);
				done();//调用了FutureTask的done();方法
				return;
			}
		}
	}
innerSet中又调用了mFuture的done方法,我们来看看done方法

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

                try {
                    result = get();//调用FutureTask的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));//取消任务,由sHandler去处理
                    message.sendToTarget();
                    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.sendToTarget();
            }
        };
 FutureTask的get()方法会等待线程的执行结果,在等待的过程中用户可能会执行mFuture的cancel方法来取消任务

 public final boolean cancel(boolean mayInterruptIfRunning) {
	return mFuture.cancel(mayInterruptIfRunning);
}
此时done()中get()会抛出CancellationException异常,捕获取消任务异常,转由sHandler去处理异常,

...
} catch (CancellationException e) {
                    message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
                            new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));//取消任务,由sHandler去处理
                    message.sendToTarget();
                    return;
                } 
				...
而get()顺利获取到结果时也转由sHandler来处理

...
message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
		new AsyncTaskResult<Result>(AsyncTask.this, result));
message.sendToTarget();
...
我们来看看sHandler,sHandler为InternalHandler,该类是AsyncTask的内部类   
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;
            }
        }
    }
    该handler的handleMessage集中来处理任务执行的完成情况
    1、MESSAGE_POST_RESULT,成功执行完任务时,调用AsyncTask的finish(result)方法,参数为返回的结果

	AsyncTask的finish(result)方法:
	    private void finish(Result result) {
        if (isCancelled()) result = null;
        onPostExecute(result);
        mStatus = Status.FINISHED;
    }
调用了onPostExecute(result)方法,并把状态改正已执行结束。
    因而AsyncTask的onPostExecute方法一般是在执行doInBackground方法之后由UI线程来执行收尾工作,

2、MESSAGE_POST_PROGRESS 执行AsyncTask的onProgressUpdate方法,一般用来在任务执行中进行进度条的更新等,该MESSAGE_POST_PROGRESS是由publishProgress方法的调用来引起的

	    protected final void publishProgress(Progress... values) {
        sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }
而publishProgress方法一般是在doInBackground中根据实际情况来更新UI线程,比如更新进度条等。
    1、MESSAGE_POST_CANCEL,取消任务,调用了AsyncTask的.onCancelled()方法
    其中onPostExecute、publishProgress、onCancelled都是由子类提供的。
    到这里AsyncTask类的使用也就很简单了,
      AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。
     onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。
    doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
    onProgressUpdate(Progress...),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
    onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
    AsyncTask的调用也很简单,只要在UI线程中执行execute方法
为了正确的使用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传入的参数。

















  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值