Android中AsyncTask分析--你所不注意的坑.doc_第1页
Android中AsyncTask分析--你所不注意的坑.doc_第2页
Android中AsyncTask分析--你所不注意的坑.doc_第3页
Android中AsyncTask分析--你所不注意的坑.doc_第4页
Android中AsyncTask分析--你所不注意的坑.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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 mTaskList; public AsyncTaskAdapter(Context context, int taskCount) mContext = context; mFactory = LayoutInflater.from(mContext); mTaskCount = taskCount; mTaskList = new ArrayList(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.executeOnE(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 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(values0); 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.你想要的并发执行上面的情况肯定不是你想要的,你想要的应该是这种情况:只需要修改一行代码:1task.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 sPoolWorkQueue = new LinkedBlockingQueue(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.mData0); 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() public Result call() throws Exception mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return postResult(doInBackground(mParams); ; mFuture = new FutureTask(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(this, result); message.sendToTarget(); return result; 3.1 按照执行过程流程,实例化完,就可以调用execute():/Params. 就相当于一个数组,是传给doInBackground的参数public final AsyncTask execute(Params. params) return executeOnExecutor(sDefaultExecutor, params); /执行逻辑public final AsyncTask 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 * or

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论