你的位置:首页 > 操作系统

[操作系统]Android中AsyncTask分析


AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

本文不分析AsyncTask的使用,它的使用教程网上一搜一大堆,本文主要分析它的内部逻辑和实现,它是怎么实现异步的,它是怎么处理多个任务的,是并发么??

一、线程任务的调度

在AsyncTask内部会创建一个类相关的线程池来管理要运行的任务,也就就是说当你调用了AsyncTask的execute()后,AsyncTask会把任务交给线程池,由线程池来管理创建Thread和运行Therad。

在Android4.0版本中它内部是有两个线程池:SerialExecutor和ThreadPoolExecutor,SerialExecutor是串行的,ThreadPoolExecutor是并发的,而默认的就是SerialExecutor的,所以你一个程序中如果用了好几个AsyncTask你就得注意了:不要忘了换成并发的线程池执行。下面演示一下,穿行的调度

1.一个简单的例子:可以看出他是一个个执行的

 
代码如下:
public class AsyncTaskDemoActivity extends Activity {   private static int ID = 0;   private static final int TASK_COUNT = 9;   private static ExecutorService SINGLE_TASK_EXECUTOR;   private static ExecutorService LIMITED_TASK_EXECUTOR;   private static ExecutorService FULL_TASK_EXECUTOR;      static {     SINGLE_TASK_EXECUTOR = (ExecutorService) Executors.newSingleThreadExecutor();     LIMITED_TASK_EXECUTOR = (ExecutorService) Executors.newFixedThreadPool(7);     FULL_TASK_EXECUTOR = (ExecutorService) Executors.newCachedThreadPool();   };      @Override   public void onCreate(Bundle icicle) {     super.onCreate(icicle);     setContentView(R.layout.asynctask_demo_activity);     String title = "AsyncTask of API " + VERSION.SDK_INT;     setTitle(title);     final ListView taskList = (ListView) findViewById(R.id.task_list);     taskList.setAdapter(new AsyncTaskAdapter(getApplication(), TASK_COUNT));   }      private class AsyncTaskAdapter extends BaseAdapter {     private Context mContext;     private LayoutInflater mFactory;     private int mTaskCount;     List<SimpleAsyncTask> mTaskList;          public AsyncTaskAdapter(Context context, int taskCount) {       mContext = context;       mFactory = LayoutInflater.from(mContext);       mTaskCount = taskCount;       mTaskList = new ArrayList<SimpleAsyncTask>(taskCount);     }          @Override     public int getCount() {       return mTaskCount;     }      @Override     public Object getItem(int position) {       return mTaskList.get(position);     }      @Override     public long getItemId(int position) {       return position;     }      @Override     public View getView(int position, View convertView, ViewGroup parent) {       if (convertView == null) {         convertView = mFactory.inflate(R.layout.asynctask_demo_item, null);         SimpleAsyncTask task = new SimpleAsyncTask((TaskItem) convertView);         /*         * It only supports five tasks at most. More tasks will be scheduled only after         * first five finish. In all, the pool size of AsyncTask is 5, at any time it only         * has 5 threads running.         */         task.execute();        // use AsyncTask#SERIAL_EXECUTOR is the same to #execute(); //        task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);         // use AsyncTask#THREAD_POOL_EXECUTOR is the same to older version #execute() (less than API 11)         // but different from newer version of #execute() //        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);         // one by one, same to newer version of #execute() //        task.executeOnExecutor(SINGLE_TASK_EXECUTOR);         // execute tasks at some limit which can be customized //        task.executeOnExecutor(LIMITED_TASK_EXECUTOR);         // no limit to thread pool size, all tasks run simultaneously         //task.executeOnExecutor(FULL_TASK_EXECUTOR);                  mTaskList.add(task);       }       return convertView;     }   }      private class SimpleAsyncTask extends AsyncTask<Void, Integer, Void> {     private TaskItem mTaskItem;     private String mName;          public SimpleAsyncTask(TaskItem item) {       mTaskItem = item;       mName = "Task #" + String.valueOf(++ID);     }          @Override     protected Void doInBackground(Void... params) {       int prog = 1;       while (prog < 101) {         SystemClock.sleep(100);         publishProgress(prog);         prog++;       }       return null;     }          @Override     protected void onPostExecute(Void result) {     }          @Override     protected void onPreExecute() {       mTaskItem.setTitle(mName);     }          @Override     protected void onProgressUpdate(Integer... values) {       mTaskItem.setProgress(values[0]);     }   } }  class TaskItem extends LinearLayout {   private TextView mTitle;   private ProgressBar mProgress;      public TaskItem(Context context, AttributeSet attrs) {     super(context, attrs);   }    public TaskItem(Context context) {     super(context);   }      public void setTitle(String title) {     if (mTitle == null) {       mTitle = (TextView) findViewById(R.id.task_name);     }     mTitle.setText(title);   }      public void setProgress(int prog) {     if (mProgress == null) {       mProgress = (ProgressBar) findViewById(R.id.task_progress);     }     mProgress.setProgress(prog);   } } 

  2.你想要的并发执行


上面的情况肯定不是你想要的,你想要的应该是这种情况:

只需要修改一行代码:
 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 

  当然也可以换成你自己的线程池。

二、源码分析

  1.成员变量:

定义了需要用到的成员,可以根据名字就能知道干什么的

//生产线程的工厂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());    }  };//存放任务的阻塞队列  private static final BlockingQueue<Runnable> sPoolWorkQueue =      new LinkedBlockingQueue<Runnable>(10);  /**   * 可以平行的执行任务!就是并发的   * An {@link Executor} that can be used to execute tasks in parallel.   */  public static final Executor THREAD_POOL_EXECUTOR      = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,          TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);  /**   * 线性执行的执行器   * An {@link Executor} that executes tasks one at a time in serial   * order. This serialization is global to a particular process.   */  public static final Executor SERIAL_EXECUTOR = new SerialExecutor();  //内部交互的handler  private static final InternalHandler sHandler = new InternalHandler();  //默认的Executor  private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

定义了需要用到的成员,可以根据名字就能知道干什么的,另外注意都是static修饰的:

  第二行的sThreadFactory是创建线程的;

  第十行的sPoolWorkQueue阻塞队列,存放任务的;

 第十七行是 THREAD_POOL_EXECUTOR是线程池,这个是并发执行的线程池;

 第26行是线性调度的线程池,SERIAL_EXECUTOR,执行完一个才会执行下一个;

 第28行是一个内部封装的Handler:InternalHandler

 第30行可以看出他默认的是线性调度的线程池, Executor sDefaultExecutor = SERIAL_EXECUTOR,看到这里你应该注意一个问题,如果程序里有好多个AsyncTask,它们就是线性调度的,这肯定可你预想的不一样,所以你别忘了换成并发的执行器。


2.内部Handler的使用:

2.1 自定义的InternalHandler(内部handler)

private static class InternalHandler extends Handler {    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})    @Override    //接受message的处理,可以看到根据状态选择是完成了,还是更新着    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;      }    }  }

  在上边handleMessage中,根据msg进行判断,是完成了还是在更新;

     任务完成调用finish方法,在其中执行你定义的onPostExecute方法,

private void finish(Result result) {    if (isCancelled()) {      onCancelled(result);    } else {      onPostExecute(result);    }    mStatus = Status.FINISHED;  } 

  3.构造方法

public AsyncTask() {    mWorker = new WorkerRunnable<Params, Result>() {      public Result call() throws Exception {        mTaskInvoked.set(true);        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);        return postResult(doInBackground(mParams));      }    };    mFuture = new FutureTask<Result>(mWorker) {      @Override      protected void done() {        try {          final Result result = get();          postResultIfNotInvoked(result);        } 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) {          postResultIfNotInvoked(null);        } catch (Throwable t) {          throw new RuntimeException("An error occured while executing "              + "doInBackground()", t);        }      }    };  }

构造方法中其实隐藏的信息很多,WorkerRunnable和FutureTask;

其中WorkerRunnable继承了Callable接口,应该是用于在未来某个线程的回调接口,在其中执行了ostResult(doInBackground(mParams));调用doInBackground并用postResult方法,把result发送到主线程。

FutureTask你看类的介绍是说控制任务的,控制任务的开始、取消等等,在这不细究,跟本文关系不大,而且我也没看明白。

第17行有一个方法:postResultIfNotInvoked(result);根据名字可以看出来是如果没有调用把把结果post出去,所以他应该是处理取消的任务的。

构造方法就分析到这,下一步就是execute():

看下postResult方法:代码很少也很简单,就是把msg发送给handler:

//用shandler把设置message,并发送。private Result postResult(Result result) {    Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,        new AsyncTaskResult<Result>(this, result));    message.sendToTarget();    return result;  }

3.1 按照执行过程流程,实例化完,就可以调用execute():


//Params... 就相当于一个数组,是传给doInBackground的参数public final AsyncTask<Params, Progress, Result> execute(Params... params) {    return executeOnExecutor(sDefaultExecutor, params);  }//执行逻辑public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,      Params... params) {    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;    exec.execute(mFuture);    return this;  } 

代码逻辑很清晰,没有几行:

20行:修改了状态;

21行:准备工作;

24行:设置参数;

25行:线程池调用执行,注意参数是mFuture。 

3.2 execute的执行逻辑

就以它定义SerialExecutor为例:

/*An {@link Executor} that executes tasks one at a time in serial   * order. This serialization is global to a particular process.*/private static class SerialExecutor implements Executor {    final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();    Runnable mActive;    public synchronized void execute(final Runnable r) {      mTasks.offer(new Runnable() {        public void run() {          try {            r.run();          } finally {            scheduleNext();          }        }      });      if (mActive == null) {        scheduleNext();      }    }    protected synchronized void scheduleNext() {      if ((mActive = mTasks.poll()) != null) {        THREAD_POOL_EXECUTOR.execute(mActive);      }    }  }

 可以看到它的方法都是用synchronized关键字修饰的,而其让他的介绍里也说了在同一时间只有一个任务在执行。

   在里边调用r.run()方法,执行完了在调用下一个。按先后顺序每次只运行一个

 

三、AsyncTask中异步的处理逻辑

没有忘了前边构造方法中的postResult(doInBackground(mParams))和postResultIfNotInvoked(result);方法吧,如果忘了翻前边去看。这两个方法把执行成功的和失败的任务都包含了。

所以我们可以设想一下它是怎么执行的:

1.在executeOnExecutor方法中给变量赋值

2.用执行器Executor另起线程执行任务

3.在Executor中一些复杂的逻辑,用FutureTask进行判断任务是否被取消,如果没有就调用回调接口call()方法,

4.在call()方法中调用了postResult(doInBackground(mParams));

5.postResult发送给主线程的Handler进行后续处理。

 

看的时候可以画下图,会很清晰,基本逻辑就这样,好AsyncTask就分析到这,欢迎纠错。。。

 转发请注明出处,原文地址:http://www.cnblogs.com/jycboy/p/asynctask_1.html