版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】AsyncTask怎么在Android中使用
这篇文章给大家介绍AsyncTask怎么在Android中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。AsyncTask简单使用public
class
MainActivity
extends
AppCompatActivity
implements
View.OnClickListener
{
private
static
final
String
TAG
=
"MainActivity";
private
ProgressDialog
mDialog;
private
AsyncTask
mAsyncTask;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDialog
=
new
ProgressDialog(this);
mDialog.setMax(100);
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setCancelable(false);
mAsyncTask
=
new
MyAsyncTask();
findViewById(R.id.tv).setOnClickListener(this);
}
@Override
public
void
onClick(View
view)
{
mAsyncTask.execute();
}
private
class
MyAsyncTask
extends
AsyncTask<Void,
Integer,
Void>
{
@Override
protected
void
onPreExecute()
{
mDialog.show();
Log.e(TAG,
Thread.currentThread().getName()
+
"
onPreExecute
");
}
@Override
protected
Void
doInBackground(Void...
params)
{
//
模拟数据的加载,耗时的任务
for
(int
i
=
0;
i
<
100;
i++)
{
try
{
Thread.sleep(80);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
publishProgress(i);
}
Log.e(TAG,
Thread.currentThread().getName()
+
"
doInBackground
");
return
null;
}
@Override
protected
void
onProgressUpdate(Integer...
values)
{
mDialog.setProgress(values[0]);
Log.e(TAG,
Thread.currentThread().getName()
+
"
onProgressUpdate
");
}
@Override
protected
void
onPostExecute(Void
result)
{
//
进行数据加载完成后的UI操作
mDialog.dismiss();
Log.e(TAG,
Thread.currentThread().getName()
+
"
onPostExecute
");
}
}
}如以上实例中,当UI线程中需求处理耗时的操作时,我们可以放在AsyncTask的doInBackground方法中执行,这个抽象的类,有几个方法需要我们重新,除了doInBackground,我们可以在onPreExecute中为这个耗时方法进行一些预处理操作,同时我们在onPostExecute中对UI进行更新操作。实例中的publishProgress对应的回调是onProgressUpdate,这样可以实时更新UI,提供更好的用户体验。AsyncTask原理AsyncTask主要有二个部分:一个是与主线的交互,另一个就是线程的管理调度。虽然可能多个AsyncTask的子类的实例,但是AsyncTask的内部Handler和ThreadPoolExecutor都是进程范围内共享的,其都是static的,也即属于类的,类的属性的作用范围是CLASSPATH,因为一个进程一个VM,所以是AsyncTask控制着进程范围内所有的子类实例。AsyncTask主要有二个部分:一个是与主线的交互,另一个就是线程的管理调度。虽然可能多个AsyncTask的子类的实例,但是AsyncTask的内部Handler和ThreadPoolExecutor都是进程范围内共享的,其都是static的,也即属于类的,类的属性的作用范围是CLASSPATH,因为一个进程一个VM,所以是AsyncTask控制着进程范围内所有的子类实例。1、与主线程交互与主线程交互是通过Handler来进行的,因为本文主要探讨AsyncTask在任务调度方面的,所以对于这部分不做细致介绍,感兴趣的朋友可以继续去看AsyncTask的源码部分。2、线程任务的调度内部会创建一个进程作用域的线程池来管理要运行的任务,也就就是说当你调用了AsyncTask#execute()后,AsyncTask会把任务交给线程池,由线程池来管理创建Thread和运行Therad。对于内部的线程池不同版本的Android的实现方式是不一样的:AsyncTask发展接下来我们先简单的了解一下AsyncTask的历史首先在android3.0之前的版本,ThreadPool的限制是5个,线程的并发量是128个,阻塞队列长度10,也就是说超过138个则会抛出异常。因此我们在使用的时候,一定要主要这部分限制,正确的使用。到了在Android3.0之后的,也许是Google也意识到这个问题,对AsyncTask的API做了调整:·execute()提交的任务,按先后顺序每次只运行一个也就是说它是按提交的次序,每次只启动一个线程执行一个任务,完成之后再执行第二个任务,也就是相当于只有一个后台线程在执行所提交的任务(Executors.newSingleThreadPool())。·新增了接口executeOnExecutor()这个接口允许开发者提供自定义的线程池来运行和调度Thread,如果你想让所有的任务都能并发同时运行,那就创建一个没有限制的线程池(Executors.newCachedThreadPool()),并提供给AsyncTask。这样这个AsyncTask实例就有了自己的线程池而不必使用AsyncTask默认的。·新增了二个预定义的线程池SERIAL_EXECUTOR和THREAD_POOL_EXECUTOR。其实THREAD_POOL_EXECUTOR并不是新增的,之前的就有,只不过之前(Android2.3)它是AsyncTask私有的,未公开而已。THREAD_POOL_EXECUTOR是一个corePoolSize为5的线程池,也就是说最多只有5个线程同时运行,超过5个的就要等待。所以如果使用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)就跟2.3版本的AsyncTask.execute()效果是一样的。而SERIAL_EXECUTOR是新增的,它的作用是保证任务执行的顺序,也就是它可以保证提交的任务确实是按照先后顺序执行的。它的内部有一个队列用来保存所提交的任务,保证当前只运行一个,这样就可以保证任务是完全按照顺序执行的,默认的execute()使用的就是这个,也就是executeOnExecutor(AsyncTask.SERIAL_EXECUTOR)与execute()是一样的。AsyncTask源码简析这里我们从AsyncTask的起点开始分析,主要有execute()、executeOnExecutor()。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;
}从代码中可以看出,execute()其实也是通过执行executeOnExecutor()方法,只是将其中的Executor设置为默认值。在executeOnExecutor()中将当前AsyncTask的状态为RUNNING,上面的switch也可以看出,每个异步任务在完成前只能执行一次。接下来就执行了onPreExecute(),当前依然在UI线程,所以我们可以在其中做一些准备工作。将我们传入的参数赋值给了mWorker.mParams最后exec.execute(mFuture)相信大家对代码中出现的mWorker,以及mFuture都会有些困惑。接下来我们来看看mWorker找到这个类:private
static
abstract
class
WorkerRunnable<Params,
Result>
implements
Callable<Result>
{
Params[]
mParams;
}可以看到是Callable的子类,且包含一个mParams用于保存我们传入的参数,下面看初始化mWorker的代码:
public
AsyncTask()
{
mWorker
=
new
WorkerRunnable<Params,
Result>()
{
public
Result
call()
throws
Exception
{
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection
unchecked
return
postResult(doInBackground(mParams));
}
};
//...
}可以看到mWorker在构造方法中完成了初始化,并且因为是一个抽象类,在这里new了一个实现类,实现了call方法,call方法中设置mTaskInvoked=true,且最终调用doInBackground(mParams)方法,并返回Result值作为参数给postResult方法.可以看到我们的doInBackground出现了,下面继续看:private
Result
postResult(Result
result)
{
@SuppressWarnings("unchecked")
Message
message
=
sHandler.obtainMessage(MESSAGE_POST_RESULT,
new
AsyncTaskResult<Result>(this,
result));
message.sendToTarget();
return
result;
}可以看到postResult中出现了我们熟悉的异步消息机制,传递了一个消息message,message.what为MESSAGE_POST_RESULT;message.object=newAsyncTaskResult(this,result);private
static
class
AsyncTaskResult<Data>
{
final
AsyncTask
mTask;
final
Data[]
mData;
AsyncTaskResult(AsyncTask
task,
Data...
data)
{
mTask
=
task;
mData
=
data;
}
}AsyncTaskResult就是一个简单的携带参数的对象。看到这,我相信大家肯定会想到,在某处肯定存在一个sHandler,且复写了其handleMessage方法等待消息的传入,以及消息的处理。private
static
final
InternalHandler
sHandler
=
new
InternalHandler();
private
static
class
InternalHandler
extends
Handler
{
@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);
break;
}
}
}这里出现了我们的handleMessage,可以看到,在接收到MESSAGE_POST_RESULT消息时,执行了result.mTask.finish(result.mData[0]);其实就是我们的AsyncTask.this.finish(result),于是看finish方法private
void
finish(Result
result)
{
if
(isCancelled())
{
onCancelled(result);
}
else
{
onPostExecute(result);
}
mStatus
=
Status.FINISHED;
}可以看到,如果我们调用了cancel()则执行onCancelled回调;正常执行的情况下调用我们的onPostExecute(result);主要这里的调用是在handler的handleMessage中,所以是在UI线程中。最后将状态置为FINISHED。mWoker看完了,应该到我们的mFuture了,依然实在构造方法中完成mFuture的初始化,将mWorker作为参数,复写了其done方法。public
AsyncTask()
{
...
mFuture
=
new
FutureTask<Result>(mWorker)
{
@Override
protected
void
done()
{
try
{
postResultIfNotInvoked(get());
}
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);
}
}
};
}任务执行结束会调用:postResultIfNotInvoked(get());get()表示获取mWorker的call的返回值,即Result.然后看postResultIfNotInvoked方法private
void
postResultIfNotInvoked(Result
result)
{
final
boolean
wasTaskInvoked
=
mTaskInvoked.get();
if
(!wasTaskInvoked)
{
postResult(result);
}
}如果mTaskInvoked不为true,则执行postResult;但是在mWorker初始化时就已经将mTaskInvoked为true,所以一般这个postResult执行不到。好了,到了这里,已经介绍完了execute方法中出现了mWorker和mFurture,不过这里一直是初始化这两个对象的代码,并没有真正的执行。下面我们看真正调用执行的地方。execute方法中的:还记得上面的execute中的:exec.execute(mFuture)exec为executeOnExecutor(sDefaultExecutor,params)中的sDefaultExecutor下面看这个sDefaultExecutorprivate
static
volatile
Executor
sDefaultExecutor
=
SERIAL_EXECUTOR;
public
static
final
Executor
SERIAL_EXECUTOR
=
new
SerialExecutor();
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);
}
}
}可以看到sDefaultExecutor其实为SerialExecutor的一个实例,其内部维持一个任务队列;直接看其execute(Runnablerunnable)方法,将runnable放入mTasks队尾;再判断当前mActive是否为空,为空则调用scheduleNext。方法scheduleNext,则直接取出任务队列中的队首任务,如果不为null则传入THREAD_POOL_EXECUTOR进行执行。下面看THREAD_POOL_EXECUTOR为何方神圣:public
static
final
Executor
THREAD_POOL_EXECUTOR
=new
ThreadPoolExecutor(CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE,
TimeUnit.SECONDS,
sPoolWorkQueue,
sThreadFactory);可以看到就是一个自己设置参数的线程池,参数为: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);
public
Thread
newThread(Runnable
r)
{
return
new
Thread(r,
"AsyncTask
#"
+
mCount.getAndIncrement());
}
};
private
static
final
BlockingQueue<Runnable>
sPoolWorkQueue
=
new
LinkedBlockingQueue<Runnable>(10);看到这里,大家可能会认为,背后原来有一个线程池,且最大支持128的线程并发,加上长度为10的阻塞队列,可能会觉得就是在快速调用138个以内的AsyncTask子类的execute方法不会出现问题,而大于138则会抛出异常。其实不是这样的,我们再仔细看一下代码,回顾一下sDefaultExecutor,真正在execute()中调用的为sDefaultExecutor.execute:private
static
class
SerialExecutor
implements
Executor
{
final
ArrayDeque<Runnable>
mTasks
=
new
ArrayDeque<Runnab
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 汽车制造合同归档体系
- 新材料研发区房产居间协议范本
- 通信工程预埋件安装合同
- 职业拳击教练招聘合同条款
- 电器生产挖掘租赁合同
- 2023年上海市中考物理二轮复习-专题10 电学压轴 题型3 电表选择、方程、重构电路
- 虚拟现实灰土工程协议
- 医院退休医生聘用合同范本
- 企业员工出行私家车租赁协议
- 2022年中考物理复习电功率计算专题-档位问题
- 基础抹灰技术交底
- 2023年英语专业四级单选题汇总
- GB/T 451.3-2002纸和纸板厚度的测定
- GB/T 31548-2015电动自行车轮胎系列
- GB/T 21661-2020塑料购物袋
- GB/T 14480.1-2015无损检测仪器涡流检测设备第1部分:仪器性能和检验
- 《 小二黑结婚 》课件-统编版高中语文选择性必修中册
- FZ/T 21001-2019自梳外毛毛条
- CB/T 3780-1997管子吊架
- 四川省阿坝藏族羌族自治州《综合知识》事业单位国考真题
- 2023年人民法院电子音像出版社招聘笔试题库及答案解析
评论
0/150
提交评论