asyncTask詳解

介紹

android UI是線程不安全的,所以想實如今子線程中刷新UI就須要藉助一些機制來實現,通常有兩種方法:handler+message;還有一種就是今天咱們要講的asyncTask。asyncTask相對handler+message要輕量級一些。java

基本用法

asyncTask是一個抽象類,所以咱們須要自定義一個類來繼承他,而且實現他的方法。android

asyncTask指定了三個泛型參數,其中Params是可變長的泛型參數,三個參數用法以下:web

Params:asyncTask傳入的參數可在後臺執行任務時使用數據庫

Progress:後臺執行任務時,若是須要在前臺顯示進度,這裏是指定泛型做爲進度單位緩存

Result:後臺執行任務完成,若是須要返回結果到前臺,這裏是指定泛型做爲返回值類型安全

除了參數下面介紹下咱們常常須要重寫的四個方法:多線程

onPreExecute():在任務執行以前調用,進行一些初始化操做,好比顯示一個進度條,這個方法是在主線程運行的。併發

doInBackground(Void... arg0):這個方法是用來執行耗時操做的,把你想要異步處理的任務的代碼放在這裏面,這個確定是在子線程執行的。因此這個方法裏面不能進行UI操做,若是想要更新UI的話,好比更新進度能夠調用publishProgress(values)方法。異步

onProgressUpdate(Integer... values):後臺執行了publishProgress(values);方法後處過來的值就能夠用來更新前臺的進度了,可見這個是在主線程執行的。async

onPostExecute(Boolean result):後臺任務執行完畢返回結果的時候會調用這個方法,將結果返回給主進程或者進行UI操做,可見也是在主進程進行的。

還有一個onCancelled()方法,當用戶取消任務的時候調用。有兩點須要注意的地方:

一、asyncTask的實例化操做和execute()方法調用必須在UI線程操做。

二、asyncTask只能被執行一次,不能重複執行。源碼裏有一個判斷:若是任務正在運行或者是已經結束的任務重複調用會拋出異常。

下面咱們來自定義一個asyncTask

public class MyAsyncTask extends AsyncTask<Void, Integer, Boolean>{
 @Override
 protected void onPreExecute() {
  // TODO Auto-generated method stub
  super.onPreExecute();
 }
 @Override
 protected Boolean doInBackground(Void... arg0) {
  // TODO Auto-generated method stub
  publishProgress(values);
  return null;
 }
 @Override
 protected void onProgressUpdate(Integer... values) {
  // TODO Auto-generated method stub
  super.onProgressUpdate(values);
 }
 @Override
 protected void onPostExecute(Boolean result) {
  // TODO Auto-generated method stub
  super.onPostExecute(result);
 }
 @Override
 protected void onCancelled() {
  // TODO Auto-generated method stub
  super.onCancelled();
 }
}

這裏咱們把AsyncTask的第一個泛型參數指定爲Void,表示在執行AsyncTask的時候不須要傳入參數給後臺任務,第二個泛型參數指定爲Integer,表示使用整型數據來做爲進度顯示單位。第三個泛型參數指定爲Boolean,表示子線程中返回的數據類型。

Android 3.0之前AsyncTask容許同時執行5個任務,線程池大小爲128個,也就是說添加了10個任務,只有前五個在執行,等有一個執行完畢纔會執行第六個,固然最多添加128個任務;3.0以後改爲了只容許同時執行一個任務,爲何變少了呢?3.0之後增長了他的靈活性,AsyncTask能夠接受自定義線程池了。

public ExecutorService executorService = Executors.newFixedThreadPool(5);  
new MyAsyncTask().executeOnExecutor(executorService);

以上代碼自定義了一個線程數爲5的線程池,一樣是能夠執行5個任務。

 線程池

說道線程池,之前還真沒接觸過,只是用用別人封裝好了的罷了。正好遇到了,也就瞭解一下,畢竟技不壓身,哈哈哈...

先來看下ExecutorService,ExecutorService是線程池的一個服務,能夠隨時關閉線程池,它裏面有幾個經常使用的線程池對象:

newCachedThreadPool()

它是一個緩存型的池子,須要建立線程的時候他會先查看有沒有之前建立過的,若是有就回收,沒有才會從新建立。適合執行一些生命週期較短的異步任務,它裏面的線程都有一個time out限制,也就是說若是一個線程超過60s沒有活動,那麼這個線程將被移除。固然前面說的回收,確定是回收的沒有time out 的線程。因此放入它裏面的線程沒必要擔憂它的結束,超過60S不活動,會自動終止。

newFixedThreadPool(count)

這個線程池跟cache池相似,它也能夠回收前面的線程,可是它的特殊之處在於同一時間它只容許固定數目的線程活動,實例化的時候能夠限定一個線程數目,好比上面提到的5個線程同步執行,固然也能夠根據CPU個數來動態設定線程個數,最好設置成核數的2N以下代碼:

 int count = Runtime.getRuntime().availableProcessors() ;
ExecutorService executorService = Executors.newFixedThreadPool(count*2);

若是指定了線程數目,在手機性能較差的狀況下可能會發生卡頓,ANR現象。fixed池子裏面的線程應該沒有time out或者是時間很長,基本不會超時。

newScheduledThreadPool(count)

能夠實現一個定長的可延時或者週期執行的線程池;

newSingleThreadExceoutor()

能夠實現一個只容許一個工做線程工做的線程池。這個池子裏面只容許一個線程在活動,順序完成全部的任務。能夠用於數據庫的操做,文件操做,或者是批量安裝應用,卸載應用等不適合高併發但有可能IO阻塞以及影響UI相應的操做。

關於多線程就講到這裏,只是講了一點基礎知識,想要深刻了解的能夠自行百度。

相關文章
相關標籤/搜索