android AsyncTask 源码解读
来源:互联网 发布:如何设置网络共享权限 编辑:程序博客网 时间:2024/05/24 05:37
android AsyncTask 源码解读
AsyncTask是对Executor和Handler的组合包装类
AsyncTask是Android提供的轻量级的异步类,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务
AsyncTask执行过程:
1、AsyncTask启动、执行过程:execute(Params… params) => executeOnExecutor() => execute(Runnable runnable) => sDefaultExecutor.execute(runnable)
2、任务执行阶段:调用顺序doInBackground()=>publishProgress()=>onProgressUpdate(),阶段性结果
3、执行结束过程调用: 1、cancel() => onCancelled()(需在doInBackground()返回后) UI线程调用。 2、调用isCancelled(),检查执行状态
public abstract class AsyncTask<Params, Progress, Result> { //Params: 传递给异步任务执行时的参数的类型//Progress: 执行的进度返回给UI线程的参数的类型//Result: 异步任务执行完后返回给UI线程的结果的类型 private static final String LOG_TAG = "AsyncTask"; private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // 获取CPU核数 private static final int CORE_POOL_SIZE = CPU_COUNT+ 1; // 核心线程数 private static final int MAXIMUM_POOL_SIZE = CPU_COUNT*2 + 1; //线程池的最大线程数 private static final int KEEP_ALIVE = 1; /* //android private static final int CORE_POOL_SIZE = 5; private static final int MAXIMUM_POOL_SIZE = 128; private static final int KEEP_ALIVE = 1; */ private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); // 实例化原子整型类mCount,则mCount的方法是线程安全的 public Thread newThread(Runnable r) { return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); } }; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); //链表阻塞队列, 容量大小128 /** * 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); public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); // 同步线程池(串行线程池): 同一时间只能执行一个任务,串行执行任务,同步方法内调用THREAD_POOL_EXECUTOR.execute()达到最终串行执行任务 private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_PROGRESS = 0x2; private static final InternalHandler sHandler = new InternalHandler(); // 静态内部类InternalHandler,其绑定了主线程的Looper和消息队列,完成消息的产生、发送、处理, private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; // 默认线程池为串行线程池 private final WorkerRunnable<Params, Result> mWorker; private final FutureTask<Result> mFuture; private volatile Status mStatus = Status.PENDING; private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); //标识当前任务是否调用执行,原子布尔型变量(原子操作就是不能被线程调度机制中断的操作) private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); // 数组双端队列,没有容量限制,其容量可自增长, mTasks的集合来保证任务的顺序执行 Runnable mActive; public synchronized void execute(final Runnable r) { // 同步方法中维护双端队列,同时操作双端队列、调用并发线程池进行任务提交、执行 mTasks.offer(new Runnable() { //通过队列的offer方法将封装了final Runnable r的new Runnable对象添加到队尾 public void run() { try { r.run(); //执行r的run方法(最后在在线程池中执行),实现任务功能 } finally { scheduleNext(); // 同步方法中调用并发线程池提交任务 } } }); if (mActive == null) { //当前没有可执行任务,调用scheduleNext方法执行一个Runnable任务 scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { //通过mTasks的poll方法出队操作,删除并返回队头的Runnable,并将返回的Runnable赋值给mActive, THREAD_POOL_EXECUTOR.execute(mActive); // 调用THREAD_POOL_EXECUTOR的execute方法,提交mActive任务,并在线程池中执行mActive.run()方法 } } } public enum Status { //Indicates that the task has not been executed yet. PENDING, // Indicates that the task is running. RUNNING, //Indicates that {@link AsyncTask#onPostExecute} has finished. FINISHED, } //异步任务的当前状态以及状态转变:PENDING=>RUNNING=>FINISHED public static void init() { sHandler.getLooper(); } public static void setDefaultExecutor(Executor exec) { sDefaultExecutor = exec; } /** * Creates a new asynchronous task. This constructor must be invoked on the UI thread. */ public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { //实现了Callable接口的call方法 public Result call() throws Exception { //call方法是在线程池的线程中执行的,而不是在主线程中运行 mTaskInvoked.set(true); //将mTaskInvoked设置为true,表示任务开始执行 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); // 将当前执行call方法的线程设置为后台线程 Result result = doInBackground(mParams); //在线程池的工作线程中执行doInBackground方法,执行实际的任务,并返回结果 Binder.flushPendingCommands(); return postResult(result); //将执行完的结果传递给postResult方法 } }; 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); } } }; } private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } } private Result postResult(Result result) { Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); // 发送“结果消息” message.sendToTarget(); return result; } public final Status getStatus() { return mStatus; } /** * Override this method to perform a computation on a background thread. The * specified parameters are the parameters passed to {@link #execute} * by the caller of this task. * * This method can call {@link #publishProgress} to publish updates on the UI thread. * * @param params The parameters of the task. * * @return A result, defined by the subclass of this task. */ protected abstract Result doInBackground(Params... params); /** * Runs on the UI thread before doInBackground() */ protected void onPreExecute() { } /** * Runs on the UI thread after doInBackground(). This method won't be invoked if the task was cancelled * @param result: The result of the operation computed by #doInBackground */ @SuppressWarnings({"UnusedDeclaration"}) protected void onPostExecute(Result result) { } /** * Runs on the UI thread after publishProgress() is invoked. * @param values The values indicating progress. */ @SuppressWarnings({"UnusedDeclaration"}) protected void onProgressUpdate(Progress... values) { } @SuppressWarnings({"UnusedParameters"}) protected void onCancelled(Result result) { onCancelled(); } protected void onCancelled() { } /** * Returns <tt>true</tt> if this task was cancelled before it completed * normally. If you are calling {@link #cancel(boolean)} on the task, * the value returned by this method should be checked periodically from * {@link #doInBackground(Object[])} to end the task as soon as possible. * * @return <tt>true</tt> if task was cancelled before it completed */ public final boolean isCancelled() { return mFuture.isCancelled(); } /** * <p>Attempts to cancel execution of this task. This attempt will * fail if the task has already completed, already been cancelled, * or could not be cancelled for some other reason. If successful, * and this task has not started when <tt>cancel</tt> is called, * this task should never run. If the task has already started, * then the <tt>mayInterruptIfRunning</tt> parameter determines * whether the thread executing this task should be interrupted in * an attempt to stop the task.</p> * * @param mayInterruptIfRunning * true:if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete. * @return false: if the task could not be cancelled, typically because it has already completed normally; true:otherwise * * @see #isCancelled() * @see #onCancelled(Object) */ // 取消当前执行任务 public final boolean cancel(boolean mayInterruptIfRunning) { //3、执行结束过程调用: cancel() => doInBackground()返回 => onCancelled() UI线程调用。 2、调用isCancelled(),检查执行状态 return mFuture.cancel(mayInterruptIfRunning); } public final Result get() throws InterruptedException, ExecutionException { return mFuture.get(); } /** * Waits if necessary for at most the given time for the computation to complete, and then retrieves its result. * @param timeout Time to wait before cancelling the operation. * @param unit The time unit for the timeout. * @return The computed result. */ //等待计算完成,获取任务状态结果 public final Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return mFuture.get(timeout, unit); } /** * Executes the task with the specified parameters. The task returns * itself (this) so that the caller can keep a reference to it. * This method must be invoked on the UI thread. * @param params The parameters of the task. * @return This instance of AsyncTask. */ //传入参数,开始执行任务 public final AsyncTask<Params, Progress, Result> execute(Params... params) { // 1、AsyncTask启动、执行过程:execute(Params... params) => executeOnExecutor() => execute(Runnable runnable) => sDefaultExecutor.execute(runnable) return executeOnExecutor(sDefaultExecutor, params); } /** * Executes the task with the specified parameters. The task returns * itself (this) so that the caller can keep a reference to it. * This method must be invoked on the UI thread. * * @param exec The executor to use. #THREAD_POOL_EXECUTOR} is available as a convenient process-wide thread pool for tasks that are loosely coupled. * @param params The parameters of the task. * * @return This instance of AsyncTask. */ 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; } public static void execute(Runnable runnable) { sDefaultExecutor.execute(runnable); //由默认线程池提交、执行任务 } protected final void publishProgress(Progress... values) { // 2、任务执行阶段:调用顺序doInBackground()=>publishProgress()=>onProgressUpdate(),阶段性结果 if (!isCancelled()) { sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } } private void finish(Result result) { if (isCancelled()) { onCancelled(result); // 任务被取消,执行onCancelled()方法 } else { onPostExecute(result); //结果发传递给onPostExecute()方法, 可在UI线程中刷新结果 } mStatus = Status.FINISHED; //AsyncTask的状态设置为完成状态 } private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); //Looper类的getMainLooper静态方法,该方法返回主线程的Looper,表示InternalHandler绑定了主线程 } @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); // 可在UI线程中刷新显示执行进度 break; } } } private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; } @SuppressWarnings({"RawUseOfParameterizedType"}) private static class AsyncTaskResult<Data> { // 封装AsyncTask与相关数据成AsyncTaskResult final AsyncTask mTask; final Data[] mData; //存储的数据 AsyncTaskResult(AsyncTask task, Data... data) { //data是可变数组 mTask = task; mData = data; } }}
AsyncTask使用关键函数:
protected void onPreExecute(); // 当任务执行之前开始调用此方法,可以在这里显示进度对话框,属UI主线程。
protected abstract Result doInBackground(Params… params);//耗时操作,例如网络请求任务。由AsyncTask线程池中的线程调用执行异步任务
protected void onPostExecute(Result result);//处理doInBackground得到的数据,能够对UI进行操作,属UI主线程
protected void onProgressUpdate(Progress… values); //可以使用进度条增加用户体验度。 属UI主线程,用于显示任务执行的进度。
protected void onCancelled(Result result); //用户调用取消时,会调用此方法,属UI主线程
使用AsyncTask类,须遵守的准则:
Task的实例必须在UI thread中创建;
execute方法必须在UI thread中调用;
不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法;
该task只能被执行一次,多次调用时将会出现异常;
示例:
public class MainActivity extends Activity{ private Button button; private Button cancel; private ImageView imageView; private ProgressDialog progressDialog; private final String IMAGE_PATH = "http://developer.android.com/images/home/kk-hero.jpg"; DownloadAsyncTask task; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView)findViewById(R.id.imageView); progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("Image Downloading"); progressDialog.setMessage("........Downloading......"); progressDialog.setCancelable(false); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v){ task = new DownloadAsyncTask(); task.execute(IMAGE_PATH); //AsyncTask任务只能被执行一次,传入参数,开始执行异步任务 //函数原型:public final AsyncTask<Params, Progress, Result> execute(Params... params) cancel.setEnabled(true); } }); cancel = (Button) findViewById(R.id.cancel); cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { task.cancel(true); //取消一个正在执行的任务 } }); cancel.setEnabled(false); } public class DownloadAsyncTask extends AsyncTask<String, Integer, byte[]> //Params: String类型,指定的URL路径,进度参数Progress: Integer类型,返回值类型Result:byte[]类型 { @Override protected void onPreExecute(){ // UI 线程执行 super.onPreExecute(); progressDialog.show(); //ProgressDialog显示出来 } @Override protected byte[] doInBackground(String... params) // 异步线程(后台线程)中执行 { ByteArrayOutputStream bos=new ByteArrayOutputStream(); byte[] imgBytes = new byte[]{}; try { URL url=new URL(params[0]); HttpURLConnection con=(HttpURLConnection)url.openConnection(); con.setConnectTimeout(5000); con.setReadTimeout(5000); con.setDoInput(true); con.connect(); InputStream is=con.getInputStream(); long maxSize=con.getContentLength(); //获取文件的大小 byte[] buffer=new byte[1024]; int len=-1; long total_length=0; while((len=is.read(buffer))!=-1){ bos.write(buffer,0,len); bos.flush(); total_length += len; int progress = ((int)(total_length/(float)maxSize) * 100); // 得到当前图片下载的进度 publishProgress(progress); //将当前进度更新给onProgressUpdate方法 } is.close(); //关闭输入流 con.disconnect(); //关闭连接 byte[] imgBytes=bos.toByteArray(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return imgBytes; } @Override protected void onProgressUpdate(Integer... values){ // UI 线程执行 super.onProgressUpdate(values); progressDialog.setProgress(values[0]); //更新ProgressDialog的进度条 } @Override protected void onPostExecute(byte[] result){ // UI 线程执行 super.onPostExecute(result); Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length); imageView.setImageBitmap(bitmap); progressDialog.dismiss(); } @Override protected void onCancelled() { //取消执行中的任务时更改UI progressDialog.setProgress(0); cancel.setEnabled(false); } }}
- android AsyncTask 源码解读
- AsyncTask源码解读
- AsyncTask源码解读
- AsyncTask异步任务 源码解读
- 面试系列之AsyncTask源码深入解读
- Android AsyncTask源码分析
- Android AsyncTask源码解析
- Android-AsyncTask源码学习
- Android源码分析--AsyncTask
- 源码分析Android AsyncTask
- Android AsyncTask源码分析
- Android AsyncTask 源码解析
- Android AsyncTask 源码解析
- Android AsyncTask 源码解析
- Android AsyncTask 源码解析
- android 源码探索--AsyncTask
- Android-AsyncTask源码分析
- Android AsyncTask 源码解析
- java 基础知识总结
- android sqlite CRUD 查询 事务
- Qt编译mysql驱动
- 无源汇有上下界可行流(网络流进阶)
- java 类、接口基础知识
- android AsyncTask 源码解读
- DNS、NAT、ARP&RARP
- Spring Cloud构建微服务架构(五)服务网关
- android 线程池 ThreadPoolExecutor
- 解决MySql 数据库 提示:1045 access denied for user 'root'@'localhost' using password yes
- windows上面画时序图(timing chart)的工具
- CCP下位机驱动程序解析
- 数据结构:树
- [Unity&GameSparks&段过滤器]通过改变注册玩家的Segment来划分玩家所在的区域