Android中从源码分析关于AsyncTask的使用
Android在框架层提供了异步任务类,AysncTask,用于执行后台任务,并将执行结果更新到UI线程。为什么要用异步任务呢?这是因为如果某个任务太耗时间的话,会阻塞UI主线程,而我们知道UI线程如果阻塞5秒的话,就会发生ANR(Application No Response)错误 ,就算没有发生,主界面上看起来也会卡卡的,这显然用户体验就不太好了。
而AsyncTask类则在不影响UI线程的情况下,另起子线程去做那些耗时比较久的任务,比如我们在TodoList中去读取图片这种情况,然后将处理后的结果再更新到UI线程,从而达到更好的用户体验。
下面是AsyncTask类的定义:
[java] view plain copy- publicabstractclassAsyncTask<Params,Progress,Result>{
- privatestaticfinalStringLOG_TAG="AsyncTask";
- ...
从上面的代码可以看出,AsyncTask是一个抽象类,所以在使用AsyncTask的时候,我们要继承它,实现一个子类,并实现其中一个方法,如下:
[java] view plain copy- classLoadImageTaskextendsAsyncTask<String,Void,ImageView>{
- @Override
- protectedImageViewdoInBackground(String...params){
- StringphotoImagePath=params[0];
- Bitmapbitmap=BitmapReader.readBigBitmapFromFile(photoImagePath,REQ_WIDTH);
- ImageViewimageView=Helper.createImageViewFromBitmap(DetailActivity.this,bitmap);
- returnimageView;
- }
- protectedvoidonPostExecute(ImageViewresult){
- imageViews.add(result);
- refreshGallery();
- }
- }
对照 AsyncTask的三个参数,Params, Progress和Result,是泛型参数。
1)Params :参数,比如例子中定义的String类型,指向一个Image的路径,这是传给AysncTask的doInBackground方法。
2)Progress:这是在执行过程中会用到的一个参数,一般在显示进度的时候会用到,在例子中不会用到,所以可以在这里指定为Void。
3)Result:这是执行的结果对象,会作为onPostExecute方法的参数,在UI线程中处理。
由上面的例子也可以看到,一般我们实现的这个子类,要实现其中的两个方法
1)doInBackground:这个方法,其实是在另外一个线程中执行的。
2)onPostExecute:而这个方法却已经回到UI线程中来执行,所以可以在这里将上一个方法中执行所得的结果在这里更新到UI线程中。
那么这里面的机制是怎么样的呢,我们就来深入地看一下,也学习一下吧。
首先我们来看一下在Activity中,我们是怎么样来使用我们这个AsyncTask的吧,代码如下:
[java] view plain copy- @Override
- protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
- if(requestCode==REQUEST_FOR_CAMERA){
- if(resultCode==RESULT_OK){
- isPhotoTaken=true;
- photoFileNames.add(tempPhotoFileName);
- }
- }elseif(requestCode==REQUEST_FOR_GALLERY){
- if(resultCode==RESULT_OK){
- isPhotoTaken=true;
- ContentResolverresolver=getContentResolver();
- Uriuri=data.getData();
- tempPhotoFileName=Helper.getImagePath(resolver,uri);
- photoFileNames.add(tempPhotoFileName);
- }
- }
- newLoadImageTask().execute(tempPhotoFileName);//调用其execute方法
- }
进入AsyncTask类中,找到execute方法,如下:
[java] view plain copy- publicfinalAsyncTask<Params,Progress,Result>execute(Params...params){
- returnexecuteOnExecutor(sDefaultExecutor,params);
- }
- publicfinalAsyncTask<Params,Progress,Result>executeOnExecutor(Executorexec,
- Params...params){
- if(mStatus!=Status.PENDING){
- switch(mStatus){
- caseRUNNING:
- thrownewIllegalStateException("Cannotexecutetask:"
- +"thetaskisalreadyrunning.");
- caseFINISHED:
- thrownewIllegalStateException("Cannotexecutetask:"
- +"thetaskhasalreadybeenexecuted"
- +"(ataskcanbeexecutedonlyonce)");
- }
- }
- mStatus=Status.RUNNING;
- onPreExecute();
- mWorker.mParams=params;
- exec.execute(mFuture);
- returnthis;
- }
接着会调用onPreExecute方法做一些处理工作,这个方法其实我们也可以在子类中自己实现,如果有什么需要处理的话,一般不用。
然后我们发现,我们传进来的参数params会被传给mWorker,然后会有一个executor来执行execute的方法,并且执行的参数是一个mFuture对象。那么这两个东西是什么呢?
接着看如下代码:
[java] view plain copy- publicAsyncTask(){
- mWorker=newWorkerRunnable<Params,Result>(){
- publicResultcall()throwsException{
- mTaskInvoked.set(true);
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- //noinspectionunchecked
- returnpostResult(doInBackground(mParams));
- }
- };
- mFuture=newFutureTask<Result>(mWorker){
- @Override
- protectedvoiddone(){
- try{
- postResultIfNotInvoked(get());
- }catch(InterruptedExceptione){
- android.util.Log.w(LOG_TAG,e);
- }catch(ExecutionExceptione){
- thrownewRuntimeException("AnerroroccuredwhileexecutingdoInBackground()",
- e.getCause());
- }catch(CancellationExceptione){
- postResultIfNotInvoked(null);
- }
- }
- };
- }
mWorker是一个WorkerRunnable对象,而实际上WorkerRunnable是AsyncTask的一个抽象内部类,实现了Callable接口,如下:
[java] view plain copy- privatestaticabstractclassWorkerRunnable<Params,Result>implementsCallable<Result>{
- Params[]mParams;
- }
- publicFutureTask(Callable<V>callable){
- if(callable==null)
- thrownewNullPointerException();
- sync=newSync(callable);
- }
而FutureTask是Java多线程模型的一部分,其间接地实现了Runnable(线程属性)接口和Future(异步任务)接口,而在上面的executeOnExecutor方法中,正是将mWorker(实现了Callable接口)对象传给它了,并被其封装到成员变量sync中,这样它们就共同表示了一个异步任务,到这里,一个异步任务也就创建完成了。
从上面executeOnExecutor的方法,也可以看到,真正执行execute是一个Executor,而在AsyncTask中,其实是SerialExecutor,我们看看其构造函数:
[java] view plain copy- privatestaticclassSerialExecutorimplementsExecutor{
- finalArrayDeque<Runnable>mTasks=newArrayDeque<Runnable>();
- RunnablemActive;
- publicsynchronizedvoidexecute(finalRunnabler){
- mTasks.offer(newRunnable(){
- publicvoidrun(){
- try{
- r.run();//在新线程中调用了我们上面传进来的FutureTask的run方法
- }finally{
- scheduleNext();
- }
- }
- });
- if(mActive==null){
- scheduleNext();
- }
- }
- protectedsynchronizedvoidscheduleNext(){
- if((mActive=mTasks.poll())!=null){
- THREAD_POOL_EXECUTOR.execute(mActive);
- }
- }
- }
从上面,我们可以看到execute方法的参数就是一个Runnable,其实也就是FutrueTask了,在这里,它会被封装到一个新的线程中作为一个任务添加到mTasks队列中,至于下面如何在THREAD_POOL_EXECUTOR中去执行mTasks我们就不再深入下去了,我们就来看看FutureTask的run方法,如下:
[java] view plain copy- publicvoidrun(){
- sync.innerRun();
- }
- voidinnerRun(){
- if(!compareAndSetState(READY,RUNNING))
- return;
- runner=Thread.currentThread();
- if(getState()==RUNNING){//recheckaftersettingthread
- Vresult;
- try{
- result=callable.call();
- }catch(Throwableex){
- setException(ex);
- return;
- }
- set(result);
- }else{
- releaseShared(0);//cancel
- }
- }
但同时我们发现,其执行完之后,是作为一个参数传递给postResult的,继续看下去:
[java] view plain copy- privateResultpostResult(Resultresult){
- @SuppressWarnings("unchecked")
- Messagemessage=sHandler.obtainMessage(MESSAGE_POST_RESULT,
- newAsyncTaskResult<Result>(this,result));
- message.sendToTarget();
- returnresult;
- }
- privatestaticfinalInternalHandlersHandler=newInternalHandler();
[java] view plain copy
- privatestaticclassInternalHandlerextendsHandler{
- @SuppressWarnings({"unchecked","RawUseOfParameterizedType"})
- @Override
- publicvoidhandleMessage(Messagemsg){
- AsyncTaskResultresult=(AsyncTaskResult)msg.obj;
- switch(msg.what){
- caseMESSAGE_POST_RESULT:
- //Thereisonlyoneresult
- result.mTask.finish(result.mData[0]);
- break;
- caseMESSAGE_POST_PROGRESS:
- result.mTask.onProgressUpdate(result.mData);
- break;
- }
- }
- }
- @SuppressWarnings({"RawUseOfParameterizedType"})
- privatestaticclassAsyncTaskResult<Data>{
- finalAsyncTaskmTask;
- finalData[]mData;
- AsyncTaskResult(AsyncTasktask,Data...data){
- mTask=task;
- mData=data;
- }
- }
- privatevoidfinish(Resultresult){
- if(isCancelled()){
- onCancelled(result);
- }else{
- onPostExecute(result);
- }
- mStatus=Status.FINISHED;
- }
转载自:http://blog.csdn.net/u013889308/article/details/20372481
更多相关文章
- Android实现简单底部导航栏 Android仿微信滑动切换效果
- Android动态加载补充 加载SD卡中的SO库
- Looper,Handler,Message
- [Android] - 对话框的小框架 Managed-Dialog
- [置顶] Android(安卓)View视图------Android如何创建一个view。
- Android开发注意点
- 第三方应用获得system权限
- Android(安卓)Handler机制之循环消息队列的退出
- Android中的Menu(菜单)的三种类型菜单的学习