日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Android多线程----异步消息处理机制之Handler

發(fā)布時(shí)間:2025/6/15 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android多线程----异步消息处理机制之Handler 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
雖然是國慶佳節(jié),但也不能停止學(xué)習(xí)的腳步,我選擇在教研室為祖國母親默默地慶生。 關(guān)于Android的多線程知識(shí),請參考本人之前的一篇博客:Android 多線程----AsyncTask異步任務(wù)詳解 在Android當(dāng)中,提供了異步消息處理機(jī)制的兩種方式來解決線程之間的通信問題,一種是今天要講的Handler的機(jī)制,還有一種就是之前講過的 AsyncTask 機(jī)制。 一、handler的引入: 我們都知道,Android UI是線程不安全的,如果在子線程中嘗試進(jìn)行UI操作,程序就有可能會(huì)崩潰。相信大家在日常的工作當(dāng)中都會(huì)經(jīng)常遇到這個(gè)問題,解決的方案應(yīng)該也是早已爛熟于心,即創(chuàng)建一個(gè)Message對象,然后借助Handler發(fā)送出去,之后在Handler的handleMessage()方法中獲得剛才發(fā)送的Message對象,然后在這里進(jìn)行UI操作就不會(huì)再出現(xiàn)崩潰了。具體實(shí)現(xiàn)代碼如下: 復(fù)制代碼 1 package com.example.androidthreadtest; 2? 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Message; 7 import android.view.View; 8 import android.view.View.OnClickListener; 9 import android.widget.Button; 10 import android.widget.TextView; 11? 12 public class MainActivity extends Activity implements OnClickListener { 13? 14 ? ? public static final int UPDATE_TEXT = 1; 15 ? ? private TextView text; 16 ? ? private Button changeText; 17 ? ? private Handler handler = new Handler() { 18 ? ? ? ? public void handleMessage(Message msg) { 19 ? ? ? ? ? ? switch (msg.what) { 20 ? ? ? ? ? ? case UPDATE_TEXT: 21 ? ? ? ? ? ? ? ? text.setText("Nice to meet you"); 22 ? ? ? ? ? ? ? ? break; 23 ? ? ? ? ? ? default: 24 ? ? ? ? ? ? ? ? break; 25 ? ? ? ? ? ? } 26 ? ? ? ? } 27 ? ? }; 28? 29 ? ? @Override 30 ? ? protected void onCreate(Bundle savedInstanceState) { 31 ? ? ? ? super.onCreate(savedInstanceState); 32 ? ? ? ? setContentView(R.layout.activity_main); 33 ? ? ? ? text = (TextView) findViewById(R.id.text); 34 ? ? ? ? changeText = (Button) findViewById(R.id.change_text); 35 ? ? ? ? changeText.setOnClickListener(this); 36 ? ? } 37? 38 ? ? @Override 39 ? ? public void onClick(View v) { 40 ? ? ? ? switch (v.getId()) { 41 ? ? ? ? case R.id.change_text: 42 ? ? ? ? ? ? new Thread(new Runnable() { 43 ? ? ? ? ? ? ? ? @Override 44 ? ? ? ? ? ? ? ? public void run() { 45 ? ? ? ? ? ? ? ? ? ? Message message = new Message(); 46 ? ? ? ? ? ? ? ? ? ? message.what = UPDATE_TEXT; 47 ? ? ? ? ? ? ? ? ? ? handler.sendMessage(message); 48 ? ? ? ? ? ? ? ? } 49 ? ? ? ? ? ? }).start(); 50 ? ? ? ? ? ? break; 51 ? ? ? ? default: 52 ? ? ? ? ? ? break; 53 ? ? ? ? } 54 ? ? } 55 } 復(fù)制代碼 上方第45行代碼也可以換成: Message msg = handler.obtainMessage();? 上面的代碼中,我們并沒有在子線程中直接進(jìn)行UI操作,而是創(chuàng)建了一個(gè)Message對象,并將它的what字段的值指定為了一個(gè)整形常量UPDATE_TEXT,用于表示更新TextView這個(gè)動(dòng)作。然后調(diào)用Handler的sendMessage()方法將這條Message發(fā)送出去。很快,Handler就會(huì)收到這條Message,并在handleMessage()方法,在這里對具體的Message進(jìn)行處理(需要注意的是,此時(shí)handleMessage()方法中的代碼是在主線程中運(yùn)行的)。如果發(fā)現(xiàn)Message的what字段的值等于UPDATE_TEXT,就將TextView顯示的內(nèi)容更新。運(yùn)行程序后,點(diǎn)擊按鈕,TextView就會(huì)顯示出更新的內(nèi)容。 二、異步消息處理機(jī)制: Handler是Android類庫提供的用于接受、傳遞和處理消息或Runnable對象的處理類,它結(jié)合Message、MessageQueue和Looper類以及當(dāng)前線程實(shí)現(xiàn)了一個(gè)消息循環(huán)機(jī)制,用于實(shí)現(xiàn)任務(wù)的異步加載和處理。整個(gè)異步消息處理流程的示意圖如下圖所示: 根據(jù)上面的圖片,我們現(xiàn)在來解析一下異步消息處理機(jī)制: Message:消息體,用于裝載需要發(fā)送的對象。 handler:它直接繼承自O(shè)bject。作用是:在子線程中發(fā)送Message或者Runnable對象到MessageQueue中;在UI線程中接收、處理從MessageQueue分發(fā)出來的Message或者Runnable對象。發(fā)送消息一般使用Handler的sendMessage()方法,而發(fā)出去的消息經(jīng)過處理后最終會(huì)傳遞到Handler的handlerMessage()方法中。 MessageQueue:用于存放Message或Runnable對象的消息隊(duì)列。它由對應(yīng)的Looper對象創(chuàng)建,并由Looper對象管理。每個(gè)線程中都只會(huì)有一個(gè)MessageQueue對象。 Looper:是每個(gè)線程中的MessageQueue的管家,循環(huán)不斷地管理MessageQueue接收和分發(fā)Message或Runnable的工作。調(diào)用Looper的loop()方法后,就會(huì)進(jìn)入到一個(gè)無限循環(huán)中然后每當(dāng)發(fā)現(xiàn)MessageQueue中存在一條消息,就會(huì)將它取出,并調(diào)用Handler的handlerMessage()方法。每個(gè)線程中也只會(huì)有一個(gè)Looper對象。 了解這些之后,我們在來看一下他們之間的聯(lián)系: 首先要明白的是,Handler和Looper對象是屬于線程內(nèi)部的數(shù)據(jù),不過也提供與外部線程的訪問接口,Handler就是公開給外部線程的接口,用于線程間的通信。Looper是由系統(tǒng)支持的用于創(chuàng)建和管理MessageQueue的依附于一個(gè)線程的循環(huán)處理對象,而Handler是用于操作線程內(nèi)部的消息隊(duì)列的,所以Handler也必須依附一個(gè)線程,而且只能是一個(gè)線程。 我們再來對異步消息處理的整個(gè)流程梳理一遍: 當(dāng)應(yīng)用程序開啟時(shí),系統(tǒng)會(huì)自動(dòng)為UI線程創(chuàng)建一個(gè)MessageQueue(消息隊(duì)列)和Looper循環(huán)處理對象。首先需要在主線程中創(chuàng)建一個(gè)Handler對象,并重寫handlerMessage()方法。然后當(dāng)子線程中需要進(jìn)行UI操作時(shí),就創(chuàng)建一個(gè)Message對象,并通過Handler將這條消息發(fā)送出去。之后這條消息就會(huì)被添加到MessageQueue的隊(duì)列中等待被處理,而Looper則會(huì)一直嘗試從MessageQueue中取出待處理消息,并找到與消息對象對應(yīng)的Handler對象,然后調(diào)用Handler的handleMessage()方法。由于Handler是在主線程中創(chuàng)建的,所以此時(shí)handleMessage()方法中的代碼也會(huì)在主線程中運(yùn)行,于是我們在這里就可以安心地進(jìn)行UI操作了。 通俗地來講,一般我們在實(shí)際的開發(fā)過程中用的比較多一種情況的就是主線程的Handler將子線程中處理過的耗時(shí)操作的結(jié)果封裝成Message(消息),并將該Message(利用主線程里的MessageQueue和Looper)傳遞到主線程中,最后主線程再根據(jù)傳遞過來的結(jié)果進(jìn)行相關(guān)的UI元素的更新,從而實(shí)現(xiàn)任務(wù)的異步加載和處理,并達(dá)到線程間的通信。 通過上一小節(jié)對Handler的一個(gè)初步認(rèn)識(shí)后,我們可以很容易總結(jié)出Handler的主要用途,下面是Android官網(wǎng)總結(jié)的關(guān)于Handler類的兩個(gè)主要用途: (1)線程間的通信: 在執(zhí)行較為耗時(shí)的操作時(shí),Handler負(fù)責(zé)將子線程中執(zhí)行的操作的結(jié)果傳遞到UI線程,然后UI線程再根據(jù)傳遞過來的結(jié)果進(jìn)行相關(guān)UI元素的更新。(上面已有說明) (2)執(zhí)行定時(shí)任務(wù): 指定任務(wù)時(shí)間,在某個(gè)具體時(shí)間或某個(gè)時(shí)間段后執(zhí)行特定的任務(wù)操作,例如使用Handler提供的postDelayed(Runnable r,long delayMillis)方法指定在多久后執(zhí)行某項(xiàng)操作,比如當(dāng)當(dāng)、淘寶、京東和微信等手機(jī)客戶端的開啟界面功能,都是通過Handler定時(shí)任務(wù)來完成的。 我們接下來講一下post。 三、post: 對于Handler的Post方式來說,它會(huì)傳遞一個(gè)Runnable對象到消息隊(duì)列中,在這個(gè)Runnable對象中,重寫run()方法。一般在這個(gè)run()方法中寫入需要在UI線程上的操作。 Post允許把一個(gè)Runnable對象入隊(duì)到消息隊(duì)列中。它的方法有:post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)。詳細(xì)解釋如下: boolean post(Runnable r):把一個(gè)Runnable入隊(duì)到消息隊(duì)列中,UI線程從消息隊(duì)列中取出這個(gè)對象后,立即執(zhí)行。 boolean postAtTime(Runnable r,long uptimeMillis):把一個(gè)Runnable入隊(duì)到消息隊(duì)列中,UI線程從消息隊(duì)列中取出這個(gè)對象后,在特定的時(shí)間執(zhí)行。 boolean postDelayed(Runnable r,long delayMillis):把一個(gè)Runnable入隊(duì)到消息隊(duì)列中,UI線程從消息隊(duì)列中取出這個(gè)對象后,延遲delayMills秒執(zhí)行 void removeCallbacks(Runnable r):從消息隊(duì)列中移除一個(gè)Runnable對象。 下面通過一個(gè)Demo,講解如何通過Handler的post方式在新啟動(dòng)的線程中修改UI組件的屬性: 復(fù)制代碼 1 package com.example.m03_threadtest01; 2? 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.view.View; 7 import android.widget.Button; 8 import android.widget.TextView; 9? 10 public class MainActivity extends Activity { 11 ? ? private Button btnMes1,btnMes2; 12 ? ? private TextView tvMessage; 13 ? ? // 聲明一個(gè)Handler對象 14 ? ? private static Handler handler=new Handler(); 15 ? ?? 16 ? ? @Override 17 ? ? protected void onCreate(Bundle savedInstanceState) { 18 ? ? ? ? super.onCreate(savedInstanceState); 19 ? ? ? ? setContentView(R.layout.activity_main); ? ? ? ? 20 ? ? ? ?? 21 ? ? ? ? btnMes1=(Button)findViewById(R.id.button1); 22 ? ? ? ? btnMes2=(Button)findViewById(R.id.button2); 23 ? ? ? ? tvMessage=(TextView)findViewById(R.id.TextView1); 24 ? ? ? ? btnMes1.setOnClickListener(new View.OnClickListener() { 25 ? ? ? ? ? ?? 26 ? ? ? ? ? ? @Override 27 ? ? ? ? ? ? public void onClick(View v) { 28 ? ? ? ? ? ? ? ? // 新啟動(dòng)一個(gè)子線程 29 ? ? ? ? ? ? ? ? new Thread(new Runnable() { ? ? ? ? ? ? ? ? ? ? 30 ? ? ? ? ? ? ? ? ? ? @Override 31 ? ? ? ? ? ? ? ? ? ? public void run() { 32 ? ? ? ? ? ? ? ? ? ? ? ? // tvMessage.setText("..."); 33 ? ? ? ? ? ? ? ? ? ? ? ? // 以上操作會(huì)報(bào)錯(cuò),無法再子線程中訪問UI組件,UI組件的屬性必須在UI線程中訪問 34 ? ? ? ? ? ? ? ? ? ? ? ? // 使用post方式修改UI組件tvMessage的Text屬性 35 ? ? ? ? ? ? ? ? ? ? ? ? handler.post(new Runnable() { ? ? ? ? ? ? ? ? ? ? 36 ? ? ? ? ? ? ? ? ? ? ? ? ? ? @Override 37 ? ? ? ? ? ? ? ? ? ? ? ? ? ? public void run() { 38 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tvMessage.setText("使用Handler.post在工作線程中發(fā)送一段執(zhí)行到消息隊(duì)列中,在主線程中執(zhí)行。"); ? ? ? ? ? ? ? ? ? ? ? ? 39 ? ? ? ? ? ? ? ? ? ? ? ? ? ? } 40 ? ? ? ? ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 41 ? ? ? ? ? ? ? ? ? ? } 42 ? ? ? ? ? ? ? ? }).start(); 43 ? ? ? ? ? ? } 44 ? ? ? ? }); 45 ? ? ? ?? 46 ? ? ? ? btnMes2.setOnClickListener(new View.OnClickListener() { 47 ? ? ? ? ? ?? 48 ? ? ? ? ? ? @Override 49 ? ? ? ? ? ? public void onClick(View v) { 50 ? ? ? ? ? ? ? ? new Thread(new Runnable() { ? ? ? ? ? ? ? ? ? ? 51 ? ? ? ? ? ? ? ? ? ? @Override 52 ? ? ? ? ? ? ? ? ? ? public void run() { 53 ? ? ? ? ? ? ? ? ? ? ? ? // 使用postDelayed方式修改UI組件tvMessage的Text屬性值 54 ? ? ? ? ? ? ? ? ? ? ? ? // 并且延遲3S執(zhí)行 55 ? ? ? ? ? ? ? ? ? ? ? ? handler.postDelayed(new Runnable() { 56 ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 57 ? ? ? ? ? ? ? ? ? ? ? ? ? ? @Override 58 ? ? ? ? ? ? ? ? ? ? ? ? ? ? public void run() { 59 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tvMessage.setText("使用Handler.postDelayed在工作線程中發(fā)送一段執(zhí)行到消息隊(duì)列中,在主線程中延遲3S執(zhí)行。"); ? ? 60 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 61 ? ? ? ? ? ? ? ? ? ? ? ? ? ? } 62 ? ? ? ? ? ? ? ? ? ? ? ? }, 3000); ? ? ? ? ? ? ? ? ? ? ? ? 63 ? ? ? ? ? ? ? ? ? ? } 64 ? ? ? ? ? ? ? ? }).start(); 65 ? ? ? ? ? ? ? ?? 66 ? ? ? ? ? ? } 67 ? ? ? ? }); 68 ? ? } 69 ? ?? 70 } 復(fù)制代碼 點(diǎn)擊按鈕,運(yùn)行結(jié)果如下: 有一點(diǎn)值得注意的是,對于Post方式而言,它其中Runnable對象的run()方法的代碼,均執(zhí)行在UI線程上(雖然是寫在子線程當(dāng)中的),所以對于這段代碼而言,不能執(zhí)行在UI線程上的操作,一樣無法使用post方式執(zhí)行,比如說訪問網(wǎng)絡(luò)。? 四、Message: Handler如果使用sendMessage的方式把消息入隊(duì)到消息隊(duì)列中,需要傳遞一個(gè)Message對象,而在Handler中,需要重寫handleMessage()方法,用于獲取工作線程傳遞過來的消息,此方法運(yùn)行在UI線程上。 對于Message對象,一般并不推薦直接使用它的構(gòu)造方法得到,而是建議通過使用Message.obtain()這個(gè)靜態(tài)的方法或者Handler.obtainMessage()獲取。Message.obtain()會(huì)從消息池中獲取一個(gè)Message對象,如果消息池中是空的,才會(huì)使用構(gòu)造方法實(shí)例化一個(gè)新Message,這樣有利于消息資源的利用。并不需要擔(dān)心消息池中的消息過多,它是有上限的,上限為10個(gè)。Handler.obtainMessage()具有多個(gè)重載方法,如果查看源碼,會(huì)發(fā)現(xiàn)其實(shí)Handler.obtainMessage()在內(nèi)部也是調(diào)用的Message.obtain()。 Handler中,與Message發(fā)送消息相關(guān)的方法有: Message obtainMessage():獲取一個(gè)Message對象。 boolean sendMessage():發(fā)送一個(gè)Message對象到消息隊(duì)列中,并在UI線程取到消息后,立即執(zhí)行。 boolean sendMessageDelayed():發(fā)送一個(gè)Message對象到消息隊(duì)列中,在UI線程取到消息后,延遲執(zhí)行。 boolean sendEmptyMessage(int what):發(fā)送一個(gè)空的Message對象到隊(duì)列中,并在UI線程取到消息后,立即執(zhí)行。 boolean sendEmptyMessageDelayed(int what,long delayMillis):發(fā)送一個(gè)空Message對象到消息隊(duì)列中,在UI線程取到消息后,延遲執(zhí)行。 void removeMessage():從消息隊(duì)列中移除一個(gè)未響應(yīng)的消息。 五、通過Handler實(shí)現(xiàn)線程間通信: 1、在Worker Thread發(fā)送消息,在MainThread中接收消息: 【實(shí)例】點(diǎn)擊反扭,將下方的TextView的內(nèi)容修改為“從網(wǎng)絡(luò)中獲取的數(shù)據(jù)” 【實(shí)際意義】點(diǎn)擊按鈕時(shí),程序訪問服務(wù)器,服務(wù)器接到請求之后,會(huì)返回字符串結(jié)果,然后更新到程序。 完整版代碼如下: XML布局文件代碼如下: 復(fù)制代碼 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/TextViewId" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="數(shù)據(jù)" /> ?? <Button android:id="@+id/ButtonId" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="發(fā)送消息"? android:layout_below="@id/TextViewId"/> </RelativeLayout>? 復(fù)制代碼 MainActivity.java代碼如下: 復(fù)制代碼 1 package com.example.test0207_handler; 2? 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Message; 7 import android.view.Menu; 8 import android.view.View; 9 import android.view.View.OnClickListener; 10 import android.widget.Button; 11 import android.widget.TextView; 12? 13 public class MainActivity extends Activity { 14? 15 ? ? private TextView textView ;? 16 ? ? private Button button ; 17 ? ? private Handler handler ; 18 ? ? @Override 19 ? ? protected void onCreate(Bundle savedInstanceState) { 20 ? ? ? ? super.onCreate(savedInstanceState); 21 ? ? ? ? setContentView(R.layout.activity_main); 22 ? ? ? ?? 23 ? ? ? ? textView = (TextView)findViewById(R.id.TextViewId) ; 24 ? ? ? ? button = (Button)findViewById(R.id.ButtonId) ; ? ? 25 ? ? ? ?? 26 ? ? ? ? handler = new MyHandler() ; 27 ? ? ? ?? 28 ? ? ? ? button.setOnClickListener(new ButtonListener()) ; 29 ? ? ? ?? 30 ? ? } 31 ? ? //在MainAthread線程中接收數(shù)據(jù),從而修改TextView的值 32 ? ? class MyHandler extends Handler { 33 ? ? ? ? @Override 34 ? ? ? ? public void handleMessage(Message msg) { 35 ? ? ? ? ? ? System.out.println("handleMessage--->"+Thread.currentThread().getName()) ;//得到當(dāng)前線程的名字 36 ? ? ? ? ? ? String s = (String)msg.obj ; 37 ? ? ? ? ? ? textView.setText(s) ; 38 ? ? ? ? } 39 ? ? ? ?? 40 ? ? } 41 ? ? //生成線程對象,讓NetworkThread線程啟動(dòng) 42 ? ? class ButtonListener implements OnClickListener { 43 ? ? ? ? @Override ? ? ? ? 44 ? ? ? ? public void onClick(View arg0) { 45 ? ? ? ? ? ? Thread t = new NetworkThread() ; 46 ? ? ? ? ? ? t.start(); 47 ? ? ? ? } 48 ? ? ? ?? 49 ? ? } 50 ? ?? 51 ? ? //在Worker Thread線程中發(fā)送數(shù)據(jù) 52 ? ? class NetworkThread extends Thread { 53 ? ? ? ? @Override? 54 ? ? ? ? public void run(){ 55 ? ? ? ? ? ?? 56 ? ? ? ? ? ? System.out.println("network--->"+Thread.currentThread().getName()) ;//得到當(dāng)前線程的名字 57 ? ? ? ? ? ?? 58 ? ? ? ? ? ? //模擬訪問網(wǎng)絡(luò):當(dāng)線程運(yùn)行時(shí),首先休眠2秒鐘 59 ? ? ? ? ? ? try { 60 ? ? ? ? ? ? ? ? Thread.sleep(2*1000) ; 61 ? ? ? ? ? ? } catch (InterruptedException e) { 62 ? ? ? ? ? ? ? ? e.printStackTrace(); 63 ? ? ? ? ? ? } 64 ? ? ? ? ? ? //變量s的值,模擬從網(wǎng)絡(luò)當(dāng)中獲取的數(shù)據(jù) 65 ? ? ? ? ? ? String s = "從網(wǎng)絡(luò)中獲取的數(shù)據(jù)" ; 66 ? ? ? ? ? ? //textView.setText(s) ; //這種做法是錯(cuò)誤的,只有在Mainthread中才能操作UI ? ? ? ? ? ? 67 ? ? ? ? ? ?? 68 ? ? ? ? ? ? //開始發(fā)送消息 69 ? ? ? ? ? ? Message msg = handler.obtainMessage() ; ? ? 70 ? ? ? ? ? ? msg.obj = s ; 71 ? ? ? ? ? ? handler.sendMessage(msg) ;//sendMessage()方法,在主線程或者Worker Thread線程中發(fā)送,都是可以的,都可以被取到 72 ? ? ? ? } 73 ? ? } ? ? 74 ? ?? 75 ? ? @Override 76 ? ? public boolean onCreateOptionsMenu(Menu menu) { 77 ? ? ? ? // Inflate the menu; this adds items to the action bar if it is present. 78 ? ? ? ? getMenuInflater().inflate(R.menu.main, menu); 79 ? ? ? ? return true; 80 ? ? } 81 ? ?? 82 } 復(fù)制代碼 這段代碼的結(jié)構(gòu),和最上面的第一章節(jié)是一樣的。 上方代碼中,我們在子線程中休眠2秒來模擬訪問網(wǎng)絡(luò)的操作。 65行:用字符串s表示從網(wǎng)絡(luò)中獲取的數(shù)據(jù);70行:然后我們把這個(gè)字符串放在Message的obj屬性當(dāng)中發(fā)送出去,并在主線程中接收(36行)。 運(yùn)行后結(jié)果如下: 點(diǎn)擊按鈕后結(jié)果如下: 點(diǎn)擊按鈕后,后臺(tái)輸出結(jié)果如下: 可以看到,子線程的名字是:Thread-1118,主線程的名字是:main。 2、在MainThread中發(fā)送消息,在Worker Thread中接收消息: 【實(shí)例】點(diǎn)擊按鈕,在在MainThread中發(fā)送消息,在Worker Thread中接收消息,并在后臺(tái)打印輸出。 【代碼】完整版代碼如下: XML布局文件代碼如下: 復(fù)制代碼 <RelativeLayout? xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:id="@+id/ButtonId" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="在主線程中發(fā)送消息" /> </RelativeLayout>? 復(fù)制代碼 MainActivity.java代碼如下: 復(fù)制代碼 1 package com.example.m03_handle01; 2? 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Looper; 7 import android.os.Message; 8 import android.util.Log; 9 import android.view.Menu; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.widget.Button; 13 public class MainActivity extends Activity { 14 ? ? private Button button ; 15 ? ? private Handler handler ; 16 ? ? @Override 17 ? ? protected void onCreate(Bundle savedInstanceState) { 18 ? ? ? ? super.onCreate(savedInstanceState); 19 ? ? ? ? setContentView(R.layout.activity_main); 20 ? ? ? ?? 21 ? ? ? ? button = (Button)findViewById(R.id.ButtonId) ; 22 ? ? ? ?? 23 ? ? ? ? //當(dāng)用戶點(diǎn)擊按鈕時(shí),發(fā)送Message的對象msg 24 ? ? ? ? button.setOnClickListener(new OnClickListener() { ?//使用匿名內(nèi)部類為button綁定監(jiān)聽器 25 ? ? ? ? ? ?? 26 ? ? ? ? ? ? @Override 27 ? ? ? ? ? ? public void onClick(View v) { 28 ? ? ? ? ? ? ? ? Log.i("onClick:", Thread.currentThread().getName()); 29 ? ? ? ? ? ? ? ? Message msg = handler.obtainMessage() ; 30 ? ? ? ? ? ? ? ? handler.sendMessage(msg) ; 31 ? ? ? ? ? ? } ? ? ? ? ? ? 32 ? ? ? ? }) ; 33 ? ? ? ?? 34 ? ? ? ? WorkerThread wt = new WorkerThread() ; 35 ? ? ? ? wt.start() ; 36 ? ? } 37? 38 ? ? //在WorkerThread生成handler 39 ? ? class WorkerThread extends ?Thread { 40 ? ? ? ? @Override 41 ? ? ? ? public void run() { 42 ? ? ? ? ? ? //準(zhǔn)備Looper對象 43 ? ? ? ? ? ? Looper.prepare() ; 44 ? ? ? ? ? ? //在WorkerThread當(dāng)中生成一個(gè)Handler對象 45 ? ? ? ? ? ? handler = new Handler() { 46 ? ? ? ? ? ? ? ? @Override 47 ? ? ? ? ? ? ? ? public void handleMessage(Message msg) { 48 ? ? ? ? ? ? ? ? ? ? Log.i("handleMessage:", Thread.currentThread().getName()); 49 ? ? ? ? ? ? ? ? ? ? Log.i("后臺(tái)輸出", "收到了消息對象"); 50 ? ? ? ? ? ? ? ? } 51 ? ? ? ? ? ? }; 52 ? ? ? ? ? ? //調(diào)用Looper的loop()方法之后,Looper對象將不斷地從消息隊(duì)列當(dāng)中取出對象,然后調(diào)用handler的handleMessage()方法,處理該消息對象 53 ? ? ? ? ? ? //如果消息隊(duì)列中沒有對象,則該線程阻塞 54 ? ? ? ? ? ? Looper.loop() ; ? //通過Looper對象將消息取出來 55 ? ? ? ? } 56 ? ? ? ?? 57 ? ? } 58 ? ?? 59 ? ?? 60 ? ? @Override 61 ? ? public boolean onCreateOptionsMenu(Menu menu) { 62 ? ? ? ? // Inflate the menu; this adds items to the action bar if it is present. 63 ? ? ? ? getMenuInflater().inflate(R.menu.main, menu); 64 ? ? ? ? return true; 65 ? ? } 66 ? ?? 67 }? 復(fù)制代碼 上方的第42行至54行代碼:這是MainThread中發(fā)送消息,在Worker Thread中接收消息的固定寫法。上面的三個(gè)步驟再重復(fù)一下: 準(zhǔn)備Looper對象 在WorkerThread當(dāng)中生成一個(gè)Handler對象 調(diào)用Looper的loop()方法之后,Looper對象將不斷地從消息隊(duì)列當(dāng)中取出對象,然后調(diào)用handler的handleMessage()方法,處理該消息對象;如果消息隊(duì)列中沒有對象,則該線程阻塞 注意,此時(shí)handleMessage()方法是在Worker Thread中運(yùn)行的。

總結(jié)

以上是生活随笔為你收集整理的Android多线程----异步消息处理机制之Handler的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。