版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】AsyncTask怎么在Android中使用
這篇文章給大家介紹AsyncTask怎么在Android中使用,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。AsyncTask簡(jiǎn)單使用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)
{
//
模擬數(shù)據(jù)的加載,耗時(shí)的任務(wù)
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)
{
//
進(jìn)行數(shù)據(jù)加載完成后的UI操作
mDialog.dismiss();
Log.e(TAG,
Thread.currentThread().getName()
+
"
onPostExecute
");
}
}
}如以上實(shí)例中,當(dāng)UI線程中需求處理耗時(shí)的操作時(shí),我們可以放在AsyncTask的doInBackground方法中執(zhí)行,這個(gè)抽象的類,有幾個(gè)方法需要我們重新,除了doInBackground,我們可以在onPreExecute中為這個(gè)耗時(shí)方法進(jìn)行一些預(yù)處理操作,同時(shí)我們?cè)趏nPostExecute中對(duì)UI進(jìn)行更新操作。實(shí)例中的publishProgress對(duì)應(yīng)的回調(diào)是onProgressUpdate,這樣可以實(shí)時(shí)更新UI,提供更好的用戶體驗(yàn)。AsyncTask原理AsyncTask主要有二個(gè)部分:一個(gè)是與主線的交互,另一個(gè)就是線程的管理調(diào)度。雖然可能多個(gè)AsyncTask的子類的實(shí)例,但是AsyncTask的內(nèi)部Handler和ThreadPoolExecutor都是進(jìn)程范圍內(nèi)共享的,其都是static的,也即屬于類的,類的屬性的作用范圍是CLASSPATH,因?yàn)橐粋€(gè)進(jìn)程一個(gè)VM,所以是AsyncTask控制著進(jìn)程范圍內(nèi)所有的子類實(shí)例。AsyncTask主要有二個(gè)部分:一個(gè)是與主線的交互,另一個(gè)就是線程的管理調(diào)度。雖然可能多個(gè)AsyncTask的子類的實(shí)例,但是AsyncTask的內(nèi)部Handler和ThreadPoolExecutor都是進(jìn)程范圍內(nèi)共享的,其都是static的,也即屬于類的,類的屬性的作用范圍是CLASSPATH,因?yàn)橐粋€(gè)進(jìn)程一個(gè)VM,所以是AsyncTask控制著進(jìn)程范圍內(nèi)所有的子類實(shí)例。1、與主線程交互與主線程交互是通過(guò)Handler來(lái)進(jìn)行的,因?yàn)楸疚闹饕接慉syncTask在任務(wù)調(diào)度方面的,所以對(duì)于這部分不做細(xì)致介紹,感興趣的朋友可以繼續(xù)去看AsyncTask的源碼部分。2、線程任務(wù)的調(diào)度內(nèi)部會(huì)創(chuàng)建一個(gè)進(jìn)程作用域的線程池來(lái)管理要運(yùn)行的任務(wù),也就就是說(shuō)當(dāng)你調(diào)用了AsyncTask#execute()后,AsyncTask會(huì)把任務(wù)交給線程池,由線程池來(lái)管理創(chuàng)建Thread和運(yùn)行Therad。對(duì)于內(nèi)部的線程池不同版本的Android的實(shí)現(xiàn)方式是不一樣的:AsyncTask發(fā)展接下來(lái)我們先簡(jiǎn)單的了解一下AsyncTask的歷史首先在android3.0之前的版本,ThreadPool的限制是5個(gè),線程的并發(fā)量是128個(gè),阻塞隊(duì)列長(zhǎng)度10,也就是說(shuō)超過(guò)138個(gè)則會(huì)拋出異常。因此我們?cè)谑褂玫臅r(shí)候,一定要主要這部分限制,正確的使用。到了在Android3.0之后的,也許是Google也意識(shí)到這個(gè)問(wèn)題,對(duì)AsyncTask的API做了調(diào)整:·execute()提交的任務(wù),按先后順序每次只運(yùn)行一個(gè)也就是說(shuō)它是按提交的次序,每次只啟動(dòng)一個(gè)線程執(zhí)行一個(gè)任務(wù),完成之后再執(zhí)行第二個(gè)任務(wù),也就是相當(dāng)于只有一個(gè)后臺(tái)線程在執(zhí)行所提交的任務(wù)(Executors.newSingleThreadPool())。·新增了接口executeOnExecutor()這個(gè)接口允許開(kāi)發(fā)者提供自定義的線程池來(lái)運(yùn)行和調(diào)度Thread,如果你想讓所有的任務(wù)都能并發(fā)同時(shí)運(yùn)行,那就創(chuàng)建一個(gè)沒(méi)有限制的線程池(Executors.newCachedThreadPool()),并提供給AsyncTask。這樣這個(gè)AsyncTask實(shí)例就有了自己的線程池而不必使用AsyncTask默認(rèn)的?!ば略隽硕€(gè)預(yù)定義的線程池SERIAL_EXECUTOR和THREAD_POOL_EXECUTOR。其實(shí)THREAD_POOL_EXECUTOR并不是新增的,之前的就有,只不過(guò)之前(Android2.3)它是AsyncTask私有的,未公開(kāi)而已。THREAD_POOL_EXECUTOR是一個(gè)corePoolSize為5的線程池,也就是說(shuō)最多只有5個(gè)線程同時(shí)運(yùn)行,超過(guò)5個(gè)的就要等待。所以如果使用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)就跟2.3版本的AsyncTask.execute()效果是一樣的。而SERIAL_EXECUTOR是新增的,它的作用是保證任務(wù)執(zhí)行的順序,也就是它可以保證提交的任務(wù)確實(shí)是按照先后順序執(zhí)行的。它的內(nèi)部有一個(gè)隊(duì)列用來(lái)保存所提交的任務(wù),保證當(dāng)前只運(yùn)行一個(gè),這樣就可以保證任務(wù)是完全按照順序執(zhí)行的,默認(rèn)的execute()使用的就是這個(gè),也就是executeOnExecutor(AsyncTask.SERIAL_EXECUTOR)與execute()是一樣的。AsyncTask源碼簡(jiǎn)析這里我們從AsyncTask的起點(diǎn)開(kāi)始分析,主要有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()其實(shí)也是通過(guò)執(zhí)行executeOnExecutor()方法,只是將其中的Executor設(shè)置為默認(rèn)值。在executeOnExecutor()中將當(dāng)前AsyncTask的狀態(tài)為RUNNING,上面的switch也可以看出,每個(gè)異步任務(wù)在完成前只能執(zhí)行一次。接下來(lái)就執(zhí)行了onPreExecute(),當(dāng)前依然在UI線程,所以我們可以在其中做一些準(zhǔn)備工作。將我們傳入的參數(shù)賦值給了mWorker.mParams最后exec.execute(mFuture)相信大家對(duì)代碼中出現(xiàn)的mWorker,以及mFuture都會(huì)有些困惑。接下來(lái)我們來(lái)看看mWorker找到這個(gè)類:private
static
abstract
class
WorkerRunnable<Params,
Result>
implements
Callable<Result>
{
Params[]
mParams;
}可以看到是Callable的子類,且包含一個(gè)mParams用于保存我們傳入的參數(shù),下面看初始化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在構(gòu)造方法中完成了初始化,并且因?yàn)槭且粋€(gè)抽象類,在這里new了一個(gè)實(shí)現(xiàn)類,實(shí)現(xiàn)了call方法,call方法中設(shè)置mTaskInvoked=true,且最終調(diào)用doInBackground(mParams)方法,并返回Result值作為參數(shù)給postResult方法.可以看到我們的doInBackground出現(xiàn)了,下面繼續(xù)看:private
Result
postResult(Result
result)
{
@SuppressWarnings("unchecked")
Message
message
=
sHandler.obtainMessage(MESSAGE_POST_RESULT,
new
AsyncTaskResult<Result>(this,
result));
message.sendToTarget();
return
result;
}可以看到postResult中出現(xiàn)了我們熟悉的異步消息機(jī)制,傳遞了一個(gè)消息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就是一個(gè)簡(jiǎn)單的攜帶參數(shù)的對(duì)象。看到這,我相信大家肯定會(huì)想到,在某處肯定存在一個(gè)sHandler,且復(fù)寫了其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;
}
}
}這里出現(xiàn)了我們的handleMessage,可以看到,在接收到MESSAGE_POST_RESULT消息時(shí),執(zhí)行了result.mTask.finish(result.mData[0]);其實(shí)就是我們的AsyncTask.this.finish(result),于是看finish方法private
void
finish(Result
result)
{
if
(isCancelled())
{
onCancelled(result);
}
else
{
onPostExecute(result);
}
mStatus
=
Status.FINISHED;
}可以看到,如果我們調(diào)用了cancel()則執(zhí)行onCancelled回調(diào);正常執(zhí)行的情況下調(diào)用我們的onPostExecute(result);主要這里的調(diào)用是在handler的handleMessage中,所以是在UI線程中。最后將狀態(tài)置為FINISHED。mWoker看完了,應(yīng)該到我們的mFuture了,依然實(shí)在構(gòu)造方法中完成mFuture的初始化,將mWorker作為參數(shù),復(fù)寫了其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);
}
}
};
}任務(wù)執(zhí)行結(jié)束會(huì)調(diào)用:postResultIfNotInvoked(get());get()表示獲取mWorker的call的返回值,即Result.然后看postResultIfNotInvoked方法private
void
postResultIfNotInvoked(Result
result)
{
final
boolean
wasTaskInvoked
=
mTaskInvoked.get();
if
(!wasTaskInvoked)
{
postResult(result);
}
}如果mTaskInvoked不為true,則執(zhí)行postResult;但是在mWorker初始化時(shí)就已經(jīng)將mTaskInvoked為true,所以一般這個(gè)postResult執(zhí)行不到。好了,到了這里,已經(jīng)介紹完了execute方法中出現(xiàn)了mWorker和mFurture,不過(guò)這里一直是初始化這兩個(gè)對(duì)象的代碼,并沒(méi)有真正的執(zhí)行。下面我們看真正調(diào)用執(zhí)行的地方。execute方法中的:還記得上面的execute中的:exec.execute(mFuture)exec為executeOnExecutor(sDefaultExecutor,params)中的sDefaultExecutor下面看這個(gè)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其實(shí)為SerialExecutor的一個(gè)實(shí)例,其內(nèi)部維持一個(gè)任務(wù)隊(duì)列;直接看其execute(Runnablerunnable)方法,將runnable放入mTasks隊(duì)尾;再判斷當(dāng)前mActive是否為空,為空則調(diào)用scheduleNext。方法scheduleNext,則直接取出任務(wù)隊(duì)列中的隊(duì)首任務(wù),如果不為null則傳入THREAD_POOL_EXECUTOR進(jìn)行執(zhí)行。下面看THREAD_POOL_EXECUTOR為何方神圣:public
static
final
Executor
THREAD_POOL_EXECUTOR
=new
ThreadPoolExecutor(CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE,
TimeUnit.SECONDS,
sPoolWorkQueue,
sThreadFactory);可以看到就是一個(gè)自己設(shè)置參數(shù)的線程池,參數(shù)為: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);看到這里,大家可能會(huì)認(rèn)為,背后原來(lái)有一個(gè)線程池,且最大支持128的線程并發(fā),加上長(zhǎng)度為10的阻塞隊(duì)列,可能會(huì)覺(jué)得就是在快速調(diào)用138個(gè)以內(nèi)的AsyncTask子類的execute方法不會(huì)出現(xiàn)問(wèn)題,而大于138則會(huì)拋出異常。其實(shí)不是這樣的,我們?cè)僮屑?xì)看一下代碼,回顧一下sDefaultExecutor,真正在execute()中調(diào)用的為sDefaultExecutor.execute:private
static
class
SerialExecutor
implements
Executor
{
final
ArrayDeque<Runnable>
mTasks
=
new
ArrayDeque<Runnab
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024版分期付款合同書
- 二零二五年能源管理評(píng)估合同能源管理協(xié)議3篇
- 無(wú)錫南洋職業(yè)技術(shù)學(xué)院《石油鉆采機(jī)械概論》2023-2024學(xué)年第一學(xué)期期末試卷
- 2024版高清影視內(nèi)容制作與版權(quán)轉(zhuǎn)讓合同
- 2025年度體育場(chǎng)館草坪除草與賽事運(yùn)營(yíng)保障合同3篇
- 2024法律顧問(wèn)協(xié)議
- 2024版建筑行業(yè)招投標(biāo)規(guī)則與協(xié)議簽訂指南版B版
- 皖江工學(xué)院《商業(yè)展示設(shè)計(jì)》2023-2024學(xué)年第一學(xué)期期末試卷
- 天津體育學(xué)院《環(huán)境科學(xué)概論(Ⅱ)》2023-2024學(xué)年第一學(xué)期期末試卷
- 塔里木職業(yè)技術(shù)學(xué)院《工筆人物畫》2023-2024學(xué)年第一學(xué)期期末試卷
- 2024年石家莊正定國(guó)際機(jī)場(chǎng)改擴(kuò)建工程合同
- 2025年度愛(ài)讀書學(xué)長(zhǎng)定制化閱讀計(jì)劃合同2篇
- 河南省信陽(yáng)市浉河區(qū)9校聯(lián)考2024-2025學(xué)年八年級(jí)上學(xué)期12月月考地理試題(含答案)
- 快速康復(fù)在骨科護(hù)理中的應(yīng)用
- 國(guó)民經(jīng)濟(jì)行業(yè)分類和代碼表(電子版)
- ICU患者外出檢查的護(hù)理
- 公司收購(gòu)設(shè)備合同范例
- GB/T 44823-2024綠色礦山評(píng)價(jià)通則
- 廣東省潮州市2023-2024學(xué)年高二上學(xué)期語(yǔ)文期末考試試卷(含答案)
- 2024年光伏發(fā)電項(xiàng)目EPC總包合同
- 漂亮的可編輯顏色魚骨圖PPT模板
評(píng)論
0/150
提交評(píng)論