【移動應用開發(fā)技術】AsyncTask怎么在Android中使用_第1頁
【移動應用開發(fā)技術】AsyncTask怎么在Android中使用_第2頁
【移動應用開發(fā)技術】AsyncTask怎么在Android中使用_第3頁
【移動應用開發(fā)技術】AsyncTask怎么在Android中使用_第4頁
【移動應用開發(fā)技術】AsyncTask怎么在Android中使用_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

【移動應用開發(fā)技術】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方法中執(zhí)行,這個抽象的類,有幾個方法需要我們重新,除了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在任務調度方面的,所以對于這部分不做細致介紹,感興趣的朋友可以繼續(xù)去看AsyncTask的源碼部分。2、線程任務的調度內部會創(chuàng)建一個進程作用域的線程池來管理要運行的任務,也就就是說當你調用了AsyncTask#execute()后,AsyncTask會把任務交給線程池,由線程池來管理創(chuàng)建Thread和運行Therad。對于內部的線程池不同版本的Android的實現方式是不一樣的:AsyncTask發(fā)展接下來我們先簡單的了解一下AsyncTask的歷史首先在android3.0之前的版本,ThreadPool的限制是5個,線程的并發(fā)量是128個,阻塞隊列長度10,也就是說超過138個則會拋出異常。因此我們在使用的時候,一定要主要這部分限制,正確的使用。到了在Android3.0之后的,也許是Google也意識到這個問題,對AsyncTask的API做了調整:·execute()提交的任務,按先后順序每次只運行一個也就是說它是按提交的次序,每次只啟動一個線程執(zhí)行一個任務,完成之后再執(zhí)行第二個任務,也就是相當于只有一個后臺線程在執(zhí)行所提交的任務(Executors.newSingleThreadPool())?!ば略隽私涌趀xecuteOnExecutor()這個接口允許開發(fā)者提供自定義的線程池來運行和調度Thread,如果你想讓所有的任務都能并發(fā)同時運行,那就創(chuàng)建一個沒有限制的線程池(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是新增的,它的作用是保證任務執(zhí)行的順序,也就是它可以保證提交的任務確實是按照先后順序執(zhí)行的。它的內部有一個隊列用來保存所提交的任務,保證當前只運行一個,這樣就可以保證任務是完全按照順序執(zhí)行的,默認的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()其實也是通過執(zhí)行executeOnExecutor()方法,只是將其中的Executor設置為默認值。在executeOnExecutor()中將當前AsyncTask的狀態(tài)為RUNNING,上面的switch也可以看出,每個異步任務在完成前只能執(zhí)行一次。接下來就執(zhí)行了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出現了,下面繼續(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中出現了我們熟悉的異步消息機制,傳遞了一個消息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消息時,執(zhí)行了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()則執(zhí)行onCancelled回調;正常執(zhí)行的情況下調用我們的onPostExecute(result);主要這里的調用是在handler的handleMessage中,所以是在UI線程中。最后將狀態(tài)置為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);

}

}

};

}任務執(zhí)行結束會調用: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初始化時就已經將mTaskInvoked為true,所以一般這個postResult執(zhí)行不到。好了,到了這里,已經介紹完了execute方法中出現了mWorker和mFurture,不過這里一直是初始化這兩個對象的代碼,并沒有真正的執(zhí)行。下面我們看真正調用執(zhí)行的地方。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進行執(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);可以看到就是一個自己設置參數的線程池,參數為: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的線程并發(fā),加上長度為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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論