【移動應用開發(fā)技術(shù)】AsyncTask怎么用_第1頁
【移動應用開發(fā)技術(shù)】AsyncTask怎么用_第2頁
【移動應用開發(fā)技術(shù)】AsyncTask怎么用_第3頁
【移動應用開發(fā)技術(shù)】AsyncTask怎么用_第4頁
【移動應用開發(fā)技術(shù)】AsyncTask怎么用_第5頁
免費預覽已結(jié)束,剩余2頁可下載查看

下載本文檔

版權(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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論