异步任务AsyncTask的实现原理

    尊重原创,转发请注明出处。


     做安卓开发,平常我的项目里很经常会用到异步任务,特别是一些获取网络数据的地方,我们都知道这种耗时操作要新起线程去获取,但是获取到数据后我们不能在非UI线程里操作控件,这个时候我们通常的做法是利用Handler进行跨线程传递信息。而AsyncTask实际上就是封装了这么一个新起Thread做耗时操作+利用Handler跨进程通信实现异步任务的这么一个过程,使我们用起来十分方便。

    

    接下来我们就从源码的角度来解析一下AsyncTask里面是如何实现这一过程的:


  先来看看AsyncTask里面的几个方法以及他们的意义:

 1.onPreExecute():这个是在异步请求之前调用的

2.doInBackground():在这里面实现异步请求

3.onPostExecute():处理异步请求回来的结果

4.onProgressUpdate():请求的进度

5.execute():开始执行这个异步任务


接下来来分析一下他的实现流程:

首先AsyncTask拥有线程池,每一个异步任务都放入到这个线程池里,来看看AsyncTask的构造函数的源码:

public AsyncTask() {
            //这里面封装调用了doInBackGround(),即实现去异步请求的操作
	        mWorker = new WorkerRunnable() {
	            public Result call() throws Exception {
	                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
	                return doInBackground(mParams);
	            }
	        };
	 
	      //而这里面封装当异步请求回来收到结果要给UI线程发送的几种消息(只是封装这么一个过程,并还没有在这里面执行这个Task)
	        mFuture = new FutureTask(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(AsyncTask.this, (Result[]) null));
	                    message.sendToTarget();//取消任务,则发送取消任务的消息
	                    return;
	                } catch (Throwable t) {
	                    throw new RuntimeException("An error occured while executing "
	                            + "doInBackground()", t);
	                }
	 
	             //没有报错或异常的话则把获取到的结果发送给UI线程
	                message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
	                        new AsyncTaskResult(AsyncTask.this, result));//完成任务,发送MESSAGE_POST_RESULT消息并传递result对象
	                message.sendToTarget();
	            }
	        };
	    }


可以看出,在AsyncTask的构造方法里,已经封装了去异步请求以及获取请求结果发送消息到UI线程的这么一个过程,只不过这只是封装一个过程,并还没有正在去触发。


我们知道当我们调用AsnycTask的execute()方法的时候将会触发这个异步任务执行,接下来看一下execute()方法里做了些什么:

public final AsyncTask 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();//这里在开启异步请求之前调这个方法
	 
	        mWorker.mParams = params;
	        sExecutor.execute(mFuture);//把任务提交到线程池,开始执行
	 
	        return this;
	}

所以当调用这个方法时,才会把异步任务提交到线程池,并开始执行上面那个 FutureTask,这个时候异步去请求数据以及 FutureTask里接收到结果往UI线程里发消息的动作才被触发。


那么UI线程里肯定要有个Handler来接收这个消息,并且调用onPostExecute(),这个Handler就是InternalHandler,他是定义在UI线程里的,接下来先看一下他的源码:

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://异步任务执行成功,获取到请求结果
	                    
	                    result.mTask.finish(result.mData[]);//finish()里面会调用onPostExecute()
	                    break;
	                case MESSAGE_POST_PROGRESS:
	                   result.mTask.onProgressUpdate(result.mData);//进度更新的消息,调用onProgressUpdate()来根据返回的进去更新UI
	                    break;
	                case MESSAGE_POST_CANCEL://取消任务的消息,则取消任务
	                    result.mTask.onCancelled();
	                    break;
	            }
	        }
	    }
通过注释可以很明了的看明白了,我们看到执行异步任务成功获取到返回结果的话,这里是调了一个finish(),那么finish()里面做了些什么呢,其实finish()里调用了 onPostExecute()。



相信通过以上对源码的解析,应该对AsyncTask的实现原理以及他里面的那几个方法有了更加深刻的理解,接下来总结一下:


其实AsyncTask的实现原理概括就是:新开线程执行异步请求+Handler发送结果到UI线程


AsyncTask的封装给我们使用异步任务的时候带来很多便捷,也更加的直观,使用起来十分容易。


关于AsyncTask的实现原理就先讲到这了,有什么地方讲的有误或者不全面,希望指正,不剩感激!







 



你可能感兴趣的:(Android开发,Android,FramWork)