博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android的AsyncTask异步任务浅析
阅读量:6343 次
发布时间:2019-06-22

本文共 3331 字,大约阅读时间需要 11 分钟。

Android的AsyncTask异步任务浅析

实现原理

内部封装了2个线程池+1个Handler(InternalHandler),1个线程池SerialExecutor任务排队,一个线程池THREAD_POOL_EXECUTOR执行任务。

常用重写的方法

  • onPreExecute:运行在主线程中,可做UI更新,显示进度条通知等。
  • doInBackground:在子线程执行任务,接收的参数类型为AsyncTask第一个泛型,返回给onPostExecute的参数类型为AsyncTask第三个泛型。
  • onProgressUpdate:运行在主线程中,doInBackground中调用publishProgress方法后即可回调到该方法中,用于UI进度更新。接收的参数类型为AsyncTask第二个泛型。
  • onPostExecute:运行在主线程中,doInBackground任务执行完毕后,就会回调到该方法中。
  • onCancelled:调用AsyncTask的cancel方法时,会回调到该方法中,内部调用Thread的interrupt方法,告诉线程池要取消任务,Thread在合适时机取消任务。
public class MyTask extends AsyncTask
{ @Override // 子线程执行任务 protected Float doInBackground(String... strings) { publishProgress(5D); return 1f; } @Override // 准备执行doInBackground任务时回调 protected void onPreExecute() { super.onPreExecute(); } @Override // doInBackground任务执行结束后回调,接收的参数为doInBackground返回的值 protected void onPostExecute(Float aFloat) { super.onPostExecute(aFloat); } @Override // doInBackground调用publishProgress会回调到该方法中 protected void onProgressUpdate(Double... values) { super.onProgressUpdate(values); } @Override // 调用AsyncTask的任务关闭后回调 protected void onCancelled() { super.onCancelled(); }}复制代码

注意事项

  1. Android4.1之前,AsyncTask类必须在主线程中加载。Android4.1之后,没有了这个要求,ActivityThread的main方法中自动加载了AsyncTask。
  2. AsyncTask对象要在主线程创建,创建时,AsyncTask构造方法中,会拿到当前线程的Looper,传给new的Handler实例,以保证Handler是在主线程中。
public AsyncTask(@Nullable Looper callbackLooper) {        // 创建AsyncTask对象时,若不传外部的Handler实例,会走到这个构造中        // 拿到当前线程的Looper,传给new的Handler,则Handler在当前创建AsyncTask对象的线程中        // 因此,若要保证Handler执行环境在主线程,必须要在主线程中创建AsyncTask对象        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()            ? getMainHandler()            : new Handler(callbackLooper);                    ......省略无关代码    }复制代码
  1. AsyncTask对象的execute方法必须在主线程中调用。execute方法有@MainThread注解。
  2. Android3.0之前AsyncTask调execute方法是并行执行任务,3.0之后增加了SerialExecutor线程池,默认选择该线程池串行执行任务,若想并行执行,则直接调executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params)方法即可。
MyTask myTask = new MyTask();// 默认在SerialExecutor线程池中串行执行myTask.execute("1");// 并行执行myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "1");复制代码
  1. 一个AsyncTask对象,只能执行一次execute方法,第二次执行就会抛异常。
@MainThread // 主线程中执行的方法,默认选择SerialExecutor线程池串行执行任务public final AsyncTask
execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params);}@MainThread // 主线程中执行的方法。外部也可直接调这个方法执行任务,自己传入线程池选择是串行还是并行。public final AsyncTask
executeOnExecutor(Executor exec, Params... params) { // 一个AsyncTask对象,若多次执行execute,走到这里,会判断任务在执行中或已结束时,都将抛异常 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;}复制代码
  1. 内存泄漏问题。采用静态的AsyncTask继承类,若要引用外部,采用弱引用。
  2. 使用多个异步操作并需要进行UI变更时,用AsyncTask会很复杂,替换Handler会更灵活。

转载于:https://juejin.im/post/5c9ac35ef265da60d82dd8f3

你可能感兴趣的文章
MySQL基础安全注意细节
查看>>
Oracle随机函数—dbms_random
查看>>
pvr 批量转换
查看>>
linux命令basename使用方法
查看>>
windows下开发库路径解决方案
查看>>
linux迁移mysql数据目录
查看>>
脚本源码安装LNMP
查看>>
Percona Server安装
查看>>
函数为左边表达式
查看>>
读书杂谈一
查看>>
winform listbox 元素显示tooltrip
查看>>
cacti安装与配置
查看>>
TF-IDF与余弦相似性的应用(一):自动提取关键词
查看>>
javascript面向对象2
查看>>
限制容器对CPU的使用 - 每天5分钟玩转 Docker 容器技术(28)
查看>>
jquery 实现的一个 随机云标签网页背景
查看>>
RPC
查看>>
android广播事件处理broadcast receive
查看>>
在eclipse 里面 修改tomcat的配置--Server Locations
查看>>
网站 mvc url 路径 设置 为 *.html 的原因
查看>>