欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android中AsyncTask與handler用法實(shí)例分析

 更新時(shí)間:2015年10月29日 14:43:58   作者:陽(yáng)光島主  
這篇文章主要介紹了Android中AsyncTask與handler用法,以實(shí)例形式較為詳細(xì)的分析了Android中AsyncTask與handler的功能、用法與相關(guān)注意事項(xiàng),并附帶完整實(shí)例源碼供讀者下載,需要的朋友可以參考下

本文實(shí)例講述了Android中AsyncTask與handler用法。分享給大家供大家參考,具體如下:

首先,我們得明確下一個(gè)概念,什么是UI線程。顧名思義,ui線程就是管理著用戶界面的那個(gè)線程!

android的ui線程操作并不是安全的,并且和用戶直接進(jìn)行界面交互的操作都必須在ui線程中進(jìn)行才可以。這種模式叫做單線程模式。

我們?cè)趩尉€程模式下編程一定要注意:不要阻塞ui線程、確保只在ui線程中訪問ui組件

當(dāng)我們要執(zhí)行一個(gè)復(fù)雜耗時(shí)的算法并且最終要將計(jì)算結(jié)果反映到ui上時(shí),我們會(huì)發(fā)現(xiàn),我們根本沒辦法同時(shí)保證上面的兩點(diǎn)要求;我們肯定會(huì)想到開啟一個(gè)新的線程,讓這個(gè)復(fù)雜耗時(shí)的任務(wù)到后臺(tái)去執(zhí)行,但是執(zhí)行完畢了呢?我們發(fā)現(xiàn),我們無法再與ui進(jìn)行交互了。
為了解決這種情況,android為我們提供了很多辦法。

1)、handler和message機(jī)制:通過顯示的拋出、捕獲消息與ui進(jìn)行交互;

2)、Activity.runOnUiThread(Runnable):如果當(dāng)前線程為ui線程,則立即執(zhí)行;否則,將參數(shù)中的線程操作放入到ui線程的事件隊(duì)列中,等待執(zhí)行。

3)、View.post(Runnable):將操作放入到message隊(duì)列中,如果放入成功,該操作將會(huì)在ui線程中執(zhí)行,并返回true,否則返回false

4)、View.postDelayed(Runnable, long)跟第三條基本一樣,只不過添加了一個(gè)延遲時(shí)間。

5)、android1.5以后為我們提供了一個(gè)工具類來搞定這個(gè)問題AsyncTask.

AsyncTask是抽象類,定義了三種泛型類型 Params,Progress,Result。

Params 啟動(dòng)任務(wù)執(zhí)行的輸入?yún)?shù),比如HTTP請(qǐng)求的URL
Progress 后臺(tái)任務(wù)執(zhí)行的百分比。
Result 后臺(tái)執(zhí)行任務(wù)最終返回的結(jié)果,比如String

用程序調(diào)用,開發(fā)者需要做的就是實(shí)現(xiàn)這些方法。

1) 子類化AsyncTask
2) 實(shí)現(xiàn)AsyncTask中定義的下面一個(gè)或幾個(gè)方法

onPreExecute(),該方法將在執(zhí)行實(shí)際的后臺(tái)操作前被UI thread調(diào)用。可以在該方法中做一些準(zhǔn)備工作,如在界面上顯示一個(gè)進(jìn)度條。
doInBackground(Params…),將在onPreExecute 方法執(zhí)行后馬上執(zhí)行,該方法運(yùn)行在后臺(tái)線程中。這里將主要負(fù)責(zé)執(zhí)行那些很耗時(shí)的后臺(tái)計(jì)算工作。可以調(diào)用 publishProgress方法來更新實(shí)時(shí)的任務(wù)進(jìn)度。該方法是抽象方法,子類必須實(shí)現(xiàn)。
onProgressUpdate(Progress…),在publishProgress方法被調(diào)用后,UI thread將調(diào)用這個(gè)方法從而在界面上展示任務(wù)的進(jìn)展情況,例如通過一個(gè)進(jìn)度條進(jìn)行展示。
onPostExecute(Result),在doInBackground 執(zhí)行完成后,onPostExecute 方法將被UI thread調(diào)用,后臺(tái)的計(jì)算結(jié)果將通過該方法傳遞到UI thread.

為了正確的使用AsyncTask類,以下是幾條必須遵守的準(zhǔn)則:

1) Task的實(shí)例必須在UI thread中創(chuàng)建
2) execute方法必須在UI thread中調(diào)用
3) 不要手動(dòng)的調(diào)用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)這幾個(gè)方法
4) 該task只能被執(zhí)行一次,否則多次調(diào)用時(shí)將會(huì)出現(xiàn)異常

package cn.com.chenzheng_java; 
import android.os.AsyncTask; 
/** 
 * 
 * @author chenzheng_java 
 * @description 異步任務(wù)AcyncTask示例 
 *   
 */ 
public class MyAsyncTask extends AsyncTask<String, Integer, Object> { 
 /** 
 * 該方法由ui線程進(jìn)行調(diào)用,用戶可以在這里盡情的訪問ui組件。 
 * 很多時(shí)候,我們會(huì)在這里顯示一個(gè)進(jìn)度條啥的,以示后臺(tái)正在 
 * 執(zhí)行某項(xiàng)功能。 
 */ 
 @Override 
 protected void onPreExecute() { 
 super.onPreExecute(); 
 } 
 /** 
 * 該方法由后臺(tái)進(jìn)程進(jìn)行調(diào)用,進(jìn)行主要的耗時(shí)的那些計(jì)算。 
 * 該方法在onPreExecute方法之后進(jìn)行調(diào)用。當(dāng)然在執(zhí)行過程中 
 * 我們可以每隔多少秒就調(diào)用一次publishProgress方法,更新 
 * 進(jìn)度信息 
 */ 
 @Override 
 protected Object doInBackground(String... params) { 
 return null; 
 } 
 /** 
 * doInBackground中調(diào)用了publishProgress之后,ui線程就會(huì) 
 * 調(diào)用該方法。你可以在這里動(dòng)態(tài)的改變進(jìn)度條的進(jìn)度,讓用戶知道 
 * 當(dāng)前的進(jìn)度。 
 */ 
 @Override 
 protected void onProgressUpdate(Integer... values) { 
 super.onProgressUpdate(values); 
 } 
 /** 
 * 當(dāng)doInBackground執(zhí)行完畢之后,由ui線程調(diào)用??梢栽谶@里 
 * 返回我們計(jì)算的最終結(jié)果給用戶。 
 */ 
 @Override 
 protected void onPostExecute(Object result) { 
 super.onPostExecute(result); 
 } 
}

下面介紹最本質(zhì)的多線程:hanlder和message機(jī)制:

為何需要多線程:

在日常應(yīng)用中,我們通常需要處理一些“后臺(tái),用戶不可見”的操作,例如說,我們需要下載一個(gè)音樂,要是你的應(yīng)用必須等用戶下載完成之后才可以進(jìn)行別的操作,那肯定讓用戶非常的不爽。這時(shí)候,我們通常的做法是,讓這些操作去后臺(tái)執(zhí)行,然后等后臺(tái)執(zhí)行完畢之后,再給用戶彈出相應(yīng)的提示信息。這時(shí)候,我們就需要使用多線程機(jī)制,然后通過創(chuàng)建一個(gè)新的線程來執(zhí)行這些操作。

明白了,實(shí)現(xiàn)需求,我們就準(zhǔn)備著手實(shí)現(xiàn)了。但是,經(jīng)過進(jìn)一步的了解,我們悲劇的發(fā)現(xiàn),android中的線程機(jī)制是,只能在UI線程中和用戶進(jìn)行交互。當(dāng)我們創(chuàng)建了一個(gè)新線程,執(zhí)行了一些后臺(tái)操作,執(zhí)行完成之后,我們想要給用戶彈出對(duì)話框以確認(rèn),但是卻悲劇的發(fā)現(xiàn),我們根本無法返回UI主線程了。(UI線程就是你當(dāng)前看到的這些交互界面所屬的線程)。

這時(shí)候,我們?nèi)绻胍獙?shí)現(xiàn)這些功能,我們就需要一個(gè)android為我們提供的handler和message機(jī)制。

先講解下編程機(jī)制:

我們通常在UI線程中創(chuàng)建一個(gè)handler,handler相當(dāng)于一個(gè)處理器,它主要負(fù)責(zé)處理和綁定到該handler的線程中的message。每一個(gè)handler都必須關(guān)聯(lián)一個(gè)looper,并且兩者是一一對(duì)應(yīng)的,注意,這點(diǎn)很重要哦!此外,looper負(fù)責(zé)從其內(nèi)部的messageQueue中拿出一個(gè)個(gè)的message給handler進(jìn)行處理。因?yàn)槲覀冞@里handler是在UI線程中實(shí)現(xiàn)的,所以經(jīng)過這么一個(gè)handler、message機(jī)制,我們就可以回到UI線程中了。

handler:處理后臺(tái)進(jìn)程返回?cái)?shù)據(jù)的工作人員。
message:后臺(tái)進(jìn)程返回的數(shù)據(jù),里面可以存儲(chǔ)bundle等數(shù)據(jù)格式
messageQueue:是線程對(duì)應(yīng)looper的一部分,負(fù)責(zé)存儲(chǔ)從后臺(tái)進(jìn)程中拋回的和當(dāng)前handler綁定的message,是一個(gè)隊(duì)列。
looper:looper相當(dāng)于一個(gè)messageQueue的管理人員,它會(huì)不停的循環(huán)的遍歷隊(duì)列,然后將符合條件的message一個(gè)個(gè)的拿出來交給handler進(jìn)行處理。

注意,handler是在UI線程中聲明的,如果我們直接用類似代碼執(zhí)行一個(gè)線程的話,實(shí)際上并沒有創(chuàng)建一個(gè)新的線程,因?yàn)閔andler已經(jīng)跟默認(rèn)的UI線程中的looper綁定了。

如果有興趣的話,可以去看下Handler的默認(rèn)空構(gòu)造函數(shù)便知道原因了,里面直接綁定了當(dāng)前UI線程的looper。

下面給出一個(gè)比較簡(jiǎn)單,并且實(shí)用的實(shí)例。

public class MainActivity extends Activity implements OnClickListener { 
  private Button btnTXT; 
  private TextView tvTXT; 
  private StringBuffer returnMsg; 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    btnTXT = (Button)findViewById(R.id.btnTXT); 
    tvTXT = (TextView)findViewById(R.id.tvTXT); 
    btnTXT.setOnClickListener(this);     
  } 
  @Override 
  public void onClick(View v) { 
    returnMsg = new StringBuffer(); 
    // 創(chuàng)建一個(gè)包含Looper的線程,這里如果沒有HandlerThread的調(diào)用,會(huì)直接將后邊的MyRunnable放到UI線程隊(duì)列(myHandler.post(new MyRunnable())) 
    HandlerThread handlerThread = new HandlerThread("handler_thread"); 
    handlerThread.start();   // 啟動(dòng)自定義處理線程 
    myHandler = new MyHandler(handlerThread.getLooper());    // 將handler綁定到新線程  
    myHandler.post(new MyRunnable());    // 在新線程中執(zhí)行任務(wù)  
  } 
  /** 主線程Handler,可以與UI控件交互 */ 
  Handler mainHanlder = new Handler(){ 
    @Override 
    public void handleMessage(Message msg) { 
      if(msg.what == 0) { 
        tvTXT.setText(returnMsg.toString());  // 與主線程控件打交道(直接訪問) 
      } 
    } 
  }; 
  /** 構(gòu)造Hanlder,不可與UI控件直接交互 */ 
  private MyHandler myHandler = null; 
  private class MyHandler extends Handler{ 
    /** 
     * 使用默認(rèn)的構(gòu)造函數(shù),會(huì)將handler綁定當(dāng)前UI線程的looper。 
     * 如果想使用多線程這里是不能使用默認(rèn)的構(gòu)造方法的。 
     */  
    public MyHandler(){ 
      super(); 
    } 
    /** 構(gòu)造函數(shù),自定義looper */ 
    public MyHandler(Looper looper) { 
      super(looper); 
    } 
    // 處理具體的message消息,繼承自父類的方法 
    @Override 
    public void handleMessage(Message msg) { 
      int what = msg.what;   
      Bundle bundle = (Bundle)msg.obj;      // 提取bundle中的信息 
      String name = bundle.getString("name"); 
      String sex = bundle.getString("sex"); 
      boolean marry = bundle.getBoolean("marray"); 
      int age = bundle.getInt("age"); 
      StringBuffer strBuf = new StringBuffer();    // 拼接bundle信息 
      strBuf.append("what = ").append(what).append("\n\n"); 
      strBuf.append("name = ").append(name).append("\n"); 
      strBuf.append("sex = ").append(sex).append("\n"); 
      strBuf.append("marry = ").append(marry).append("\n"); 
      strBuf.append("age = ").append(age).append("\n\n"); 
      strBuf.append("http://blog.csdn.net/sunboy_2050"); 
      returnMsg = returnMsg.append(strBuf);  // 保存要顯示的結(jié)果 
      mainHanlder.sendEmptyMessage(0);    // 向主線程mainHanlder發(fā)送消息,與UI控件交互顯示結(jié)果 
      super.handleMessage(msg); 
    } 
  } 
  // 構(gòu)造Runnable,處理后臺(tái)業(yè)務(wù)邏輯,如下載 
  private class MyRunnable implements Runnable{ 
    @Override 
    public void run() { 
      try { 
        Message msg = Message.obtain(myHandler);  // 捕獲myHandler消息
        msg.what = 10; 
        Bundle bundle = new Bundle();        // 封裝bundle信息 
        bundle.putString("name", "yanggang"); 
        bundle.putString("sex", "pure boy"); 
        bundle.putBoolean("marry", false); 
        bundle.putInt("age", 18); 
        msg.obj = bundle; 
        long thID = Thread.currentThread().getId(); 
        returnMsg.append(thID).append(" : send msg start...").append("\n"); 
        msg.sendToTarget();   // 向myHandler發(fā)送消息 
        Thread.sleep(3000); 
      } catch (Exception e) { 
        Log.i("", "Runnable send msg error..."); 
        e.printStackTrace(); 
      } 
    } 
  } 
}

運(yùn)行結(jié)果:

完整實(shí)例代碼代碼點(diǎn)擊此處本站下載。

希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Android自定義可控制速度的跑馬燈

    Android自定義可控制速度的跑馬燈

    這篇文章主要為大家詳細(xì)介紹了Android自定義可控制速度的跑馬燈,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 基于標(biāo)準(zhǔn)http實(shí)現(xiàn)Android多文件上傳

    基于標(biāo)準(zhǔn)http實(shí)現(xiàn)Android多文件上傳

    這篇文章主要介紹了基于標(biāo)準(zhǔn)http實(shí)現(xiàn)Android多文件上傳的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android PickerView滾動(dòng)選擇器的使用方法

    Android PickerView滾動(dòng)選擇器的使用方法

    這篇文章主要為大家詳細(xì)介紹了Android PickerView滾動(dòng)選擇器的使用方法,感興趣的小伙伴們可以參考一下
    2016-03-03
  • 基于android實(shí)現(xiàn)五子棋開發(fā)

    基于android實(shí)現(xiàn)五子棋開發(fā)

    這篇文章主要為大家詳細(xì)介紹了基于android實(shí)現(xiàn)五子棋開發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • Android中PackageManager使用詳解

    Android中PackageManager使用詳解

    PackageManger的主要職責(zé)是管理應(yīng)用程序包,通過它可以獲取應(yīng)用程序信息,這篇文章主要給大家介紹了關(guān)于Android中PackageManager使用的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Android Root設(shè)備中的su權(quán)限獲取和使用詳解

    Android Root設(shè)備中的su權(quán)限獲取和使用詳解

    本篇文章主要介紹了Android Root設(shè)備中的su權(quán)限獲取和使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • Android多進(jìn)程間采用AIDL方式進(jìn)行通信

    Android多進(jìn)程間采用AIDL方式進(jìn)行通信

    這篇文章主要為大家詳細(xì)介紹了Android多進(jìn)程間采用AIDL方式進(jìn)行通信,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • android實(shí)現(xiàn)添加耳機(jī)狀態(tài)圖標(biāo)的方法

    android實(shí)現(xiàn)添加耳機(jī)狀態(tài)圖標(biāo)的方法

    這篇文章主要介紹了android實(shí)現(xiàn)添加耳機(jī)狀態(tài)圖標(biāo)的方法,較為詳細(xì)的分析了Android實(shí)現(xiàn)添加耳機(jī)圖標(biāo)的原理與相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • Android實(shí)現(xiàn)背景圖片輪播

    Android實(shí)現(xiàn)背景圖片輪播

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)背景圖片輪播,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • TabLayout用法詳解及自定義樣式

    TabLayout用法詳解及自定義樣式

    這篇文章主要介紹了TabLayout用法詳解及自定義樣式的相關(guān)資料,需要的朋友可以參考下
    2017-01-01

最新評(píng)論