




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
【移動應用開發(fā)技術(shù)】AsyncTask怎么用
這篇文章主要介紹了AsyncTask怎么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓在下帶著大家一起了解一下。AsyncTask,相信大家已經(jīng)很熟悉了。它的內(nèi)部封裝了Thread和Handler,這讓我們可以將一些耗時操作放到AsyncTask,并且能將結(jié)果及時更新到UI上。AsyncTask主要用于短時間耗時操作,長時間耗時操作不建議使用AsyncTask。private
class
DownloadFilesTask
extends
AsyncTask<URL,
Integer,
Long>
{
protected
void
onPreExecute()
{
showProgress();
}
protected
Long
doInBackground(URL...
urls)
{
int
count
=
urls.length;
long
totalSize
=
0;
for
(int
i
=
0;
i
<
count;
i++)
{
totalSize
+=
Downloader.downloadFile(urls[i]);
publishProgress((int)
((i
/
(float)
count)
*
100));
//
Escape
early
if
cancel()
is
called
if
(isCancelled())
break;
}
return
totalSize;
}
protected
void
onProgressUpdate(Integer...
progress)
{
setProgressPercent(progress[0]);
}
protected
void
onPostExecute(Long
result)
{
showDialog("Downloaded
"
+
result
+
"
bytes");
}
}
復制代碼AsyncTask是一個抽象類,我們要使用時必須自定義一個類繼承于它。AsyncTask的原型為:public
abstract
class
AsyncTask<Params,
Progress,
Result>
{}
復制代碼它接收三個泛型參數(shù),分別表示參數(shù)類型、進度類型、結(jié)果類型。上述的例子中DownloadFilesTask接收參數(shù)類型為URL類型,使用Integer類型表示任務(wù)進度,最終的任務(wù)結(jié)果是一個Long類型。注意:上面三個泛型類型不一定都得用一個明確的類型,對于沒有使用的類型,可以使用Void類型代替。注意:上面三個泛型類型不一定都得用一個明確的類型,對于沒有使用的類型,可以使用Void類型代替。繼承AsyncTask至少需要重寫doInBackground方法,同時AsyncTask也提供了另外三個方法供我們重寫,分別是onPreExecute、onProgressUpdate、onPostExecute。onPreExecute方法。在任務(wù)開始執(zhí)行之前執(zhí)行,它運行在UI線程中。通常我們可以在這里展示一個等待進度條。doInBackground方法。貫穿整個耗時任務(wù),它運行在子線程中。在這里執(zhí)行耗時操作。onProgressUpdate方法。貫穿整個耗時任務(wù),在publishProgress方法被調(diào)用后執(zhí)行,它運行在UI線程中。通常用于展示整個任務(wù)的一個進度。onProgressUpdate方法。在任務(wù)接收后調(diào)用,doInBackground的返回結(jié)果會透傳給onPostExecute的參數(shù)值,它運行在主線程中。通常我們從這里獲取任務(wù)執(zhí)行完成后的結(jié)果數(shù)據(jù)。AsyncTask類必須在UI線程加載。(在4.1系統(tǒng)版本以上會自動完成)AsyncTask對象必須在UI線程創(chuàng)建,也就是說AsyncTask的構(gòu)造方法必須在UI線程中調(diào)用。(經(jīng)過測試AsyncTask對象可以在子線程創(chuàng)建,只要保證execute方法在UI線程執(zhí)行就OK的。但是沒有人會這樣做,因為多此一舉!?。。〆xecute方法必須在UI線程中調(diào)用。這樣做是保證onPreExecute方法運行在UI線程。不要主動調(diào)用onPreExecute、doInBackground、onProgressUpdate、onProgressUpdate方法。單線程下,AsyncTask對象的任務(wù)只能執(zhí)行一次,否則會報運行時錯誤。在AsyncTask誕生之初,任務(wù)是在一個后臺線程中順序執(zhí)行的。從Android1.6開始,就變成了可以在后臺線程中并行執(zhí)行任務(wù)。然后,到了Android3.0版本,又改成了單線程順序執(zhí)行,以此避免并發(fā)任務(wù)產(chǎn)生的錯誤行為。為了驗證上述結(jié)論,下面看一個Demo例子。public
class
MainActivity
extends
Activity
{
public
static
final
String
TAG
=
"MyApplication";
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new
MyTask("task1").execute();
new
MyTask("task2").execute();
new
MyTask("task3").execute();
new
MyTask("task4").execute();
new
MyTask("task5").execute();
new
MyTask("task6").execute();
}
private
class
MyTask
extends
AsyncTask<Void,
Void,
Void>
{
private
String
taskName;
MyTask(String
taskName)
{
this.taskName
=
taskName;
}
@Override
protected
Void
doInBackground(Void...
integers)
{
try
{
Thread.sleep(6000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
return
null;
}
@Override
protected
void
onPostExecute(Void
aVoid)
{
SimpleDateFormat
df
=
new
SimpleDateFormat("yyyy-MM-dd
HH:mm:ss");
Log.e(TAG,
taskName
+
"
finish
at:
"
+
df.format(new
Date()));
}
}
}
復制代碼這個例子比較簡單,就是在MainActivity啟動時,執(zhí)行了六次MyTask,并將任務(wù)執(zhí)行后的時間節(jié)點打印出來。https://upload-images.jianshu.io/upload_images/3117364-9542dd4c445329c9.png?imageMogr2/auto-orient/strip手機的系統(tǒng)版本是Android8.0,從上面的Log信息可以看出,AsyncTask的確是串行執(zhí)行的。由于現(xiàn)有測試機最低系統(tǒng)版本都是Android4.1,已經(jīng)很難找到Android3.0以下的老古董機子了????,所以我們只能通過源碼去驗證Android1.6到Android3.0期間,AsyncTask是否是并行執(zhí)行的。Android2.3版本AsyncTask是否串行或者并行執(zhí)行,取決于它的execute方法。public
final
AsyncTask<Params,
Progress,
Result>
execute(Params...
params)
{
...省略
mWorker.mParams
=
params;
sExecutor.execute(mFuture);
return
this;
}
復制代碼而execute方法中通過sExecutor,實際為ThreadPoolExecutor對象,它的初始化如下所示。private
static
final
ThreadPoolExecutor
sExecutor
=
new
ThreadPoolExecutor(CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE,
TimeUnit.SECONDS,
sWorkQueue,
sThreadFactory);
復制代碼ThreadPoolExecutor是一個多線程容器,其中可以創(chuàng)建多個線程來執(zhí)行多個任務(wù)。由此驗證了Android1.6版本到Android3.0版本直接,AsyncTask執(zhí)行任務(wù)的機制的確也現(xiàn)在的機制不一樣,它可以讓任務(wù)并行執(zhí)行。Android8.0版本我們對比一下Android8.0版本的execute方法。public
final
AsyncTask<Params,
Progress,
Result>
execute(Params...
params)
{
return
executeOnExecutor(sDefaultExecutor,
params);
}public
final
AsyncTask<Params,
Progress,
Result>
executeOnExecutor(Executor
exec,
Params...
params)
{
...省略
mWorker.mParams
=
params;
exec.execute(mFuture);
return
this;
}
復制代碼execute方法中調(diào)用了executeOnExecutor方法,并將sDefaultExecutor作為Executor對象傳遞進去,sDefaultExecutor的初始化如下所示。private
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();
//任務(wù)執(zhí)行完畢后繼續(xù)執(zhí)行scheduleNext方法
}
}
});
if
(mActive
==
null)
{
//第一個任務(wù)會執(zhí)行該方法
scheduleNext();
}
}
protected
synchronized
void
scheduleNext()
{
if
((mActive
=
mTasks.poll())
!=
null)
{
//判斷mTask隊列中是否有下一個任務(wù),有則取出來執(zhí)行
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
復制代碼可以看到,在Android8.0版本中,創(chuàng)建了一個ArrayDeque隊列,每次只從隊列中獲取一個任務(wù)執(zhí)行,執(zhí)行完畢后會繼續(xù)判斷隊列中是否有任務(wù),如果有則取出來執(zhí)行,直到所有任務(wù)執(zhí)行完畢為止。由此可見,Android8.0版本執(zhí)行任務(wù)是串行執(zhí)行的。如果我們想改變AsyncTask這種默認行為呢,可以修改么?答案是肯定的。我們可以直接調(diào)用AsyncTask的executeOnExecutor方法,并將一個Executor對象傳遞過去,就能變成并行的執(zhí)行方法了。對于上面的例子,可以這樣改動。public
class
MainActivity
extends
Activity
{
public
static
final
String
TAG
=
"MyApplication";
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new
MyTask("task1").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new
MyTask("task2").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new
MyTask("task3").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new
MyTask("task4").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new
MyTask("task5").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new
MyTask("task6").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private
class
MyTask
extends
AsyncTask<Void,
Void,
Void>
{
private
String
taskName;
MyTask(String
taskName)
{
this.taskName
=
taskName;
}
@Override
protected
Void
doInBackground(Void...
integers)
{
try
{
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 班主任在班級活動中的引導角色計劃
- 合同范本音樂app
- 股骨頸骨折護理查房
- 班級班規(guī)的制定與執(zhí)行計劃
- 2025年自然拼讀2級標準課件材料
- 學校周邊安全環(huán)境的構(gòu)建計劃
- 建立有效的會議記錄機制計劃
- 第3課 中華文明的起源2024-2025學年新教材七年級上冊歷史新教學設(shè)計(統(tǒng)編版2024)
- 以活動促學習的班級實踐計劃
- 《貴州水城礦業(yè)股份有限公司水城縣米籮煤礦(新立一期)(延續(xù))礦產(chǎn)資源綠色開發(fā)利用方案(三合一)》評審意見
- 壓力容器安全風險管控清單(日管控、周排查、月調(diào)度)
- 麻醉性鎮(zhèn)痛藥物的處方點評
- 2023年電腦印刷設(shè)計考試題庫及答案
- 《C4D》課程教學標準
- 2024年遼寧鐵道職業(yè)技術(shù)學院高職單招(英語/數(shù)學/語文)筆試歷年參考題庫含答案解析
- 養(yǎng)肝護肝科普課件
- 康復科護士的康復護理計劃的個性化制定
- 小學英語新思維朗文2A知識清單總結(jié)期末復習資料
- 《京劇的角色》課件
- 幼兒園大班科學《7的組成和分解》
- 《項脊軒志》公開課課件【一等獎】
評論
0/150
提交評論