Android中的消息机制:Handler消息传递机制
參考《瘋狂android講義》第2版3.5 P214
一、背景
出于性能優(yōu)化考慮,Android的UI操作并不是線程安全的,這意味著如果有多個線程并發(fā)操作UI組件,可能導(dǎo)致線程安全問題。為了解決這個問題,Android制定了一條簡單的原則:只允許UI線程(亦即主線程)修改Activity中的UI組件。
當(dāng)一個程序第一次啟動時,Android會同時啟動一條主線程,主線程主要負(fù)責(zé)處理與UI相關(guān)的事件,如用戶的按鍵事件、用戶接觸屏幕的事件、屏幕繪圖事件,并把相關(guān)的事件分發(fā)到相應(yīng)的組件進(jìn)行處理,所以主線程通常又叫做UI線程。
二、使用Handler的兩種常見原因
1、只能在主UI中修改UI。但實(shí)際上,有部分UI需要在子線程中控制其修改邏輯,因此子線程需要通過handler通知主線程修改UI。這在游戲開發(fā)中尤其常見,比如需要讓新啟動的線程周期性的改變UI。
2、為避免ANR,應(yīng)該在子線程中執(zhí)行耗時較長的操作,而此操作完成后,有可能需要通知主線程修改UI。
三、基本原理及步驟
1、Handler的作用主要有2個:
(1)發(fā)送消息。
(2)獲取、處理消息。
2、基本原理:為了讓主線程能及時處理子線程發(fā)送的消息,顯然只能通過回調(diào)的方法來實(shí)現(xiàn)----開發(fā)者只要重寫Handler類中的方法,當(dāng)新啟動的線程發(fā)送消息時,消息會發(fā)送至與之關(guān)聯(lián)的MessageQueue,而Handler會不斷的從MessageQuere中獲取并處理消息-----這將導(dǎo)致Handler類中處理消息的方法被回調(diào)。
3、在線程中使用Handler的基本步驟如下:
在被調(diào)用線程中完成以下內(nèi)容:
(1)調(diào)用 Looper的prepare()方法為當(dāng)前線程創(chuàng)建Looper對象,創(chuàng)建Looper對象時,它的構(gòu)造器會創(chuàng)建與之配套的MessageQueue。
(2)有了Looper之后,創(chuàng)建Handler子類的實(shí)例,重寫HandlerMessage()方法,該方法負(fù)責(zé)處理來自其它線程的消息。
(3)調(diào)用Looper的loop()方法啟動Looper。
注:若被調(diào)用線程是主線程類,由于系統(tǒng)自動為主線程創(chuàng)建了Looper的實(shí)例,因此第一、三步驟可省略,而只需要做第2步即可。
在調(diào)用線程中完成:
(1)創(chuàng)建nessage,并填充內(nèi)容。
(2)使用被調(diào)用類創(chuàng)建的Handler實(shí)例,調(diào)用sendMessage(Message msg)方法。
四、實(shí)例
1、主線程接收數(shù)據(jù),并將之發(fā)送至子線程中完成一些耗時操作
package com.ljh.handlerdemo1;import java.util.ArrayList; import java.util.List;import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.app.Activity; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast;public class MainActivity extends Activity {private final String UPPER_NUMBER = "upper";private CalThread calThread;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);calThread = new CalThread();Thread t = new Thread(calThread);t.start();}public void cal(View v) {EditText et_digit = (EditText) findViewById(R.id.et_digit);Message msg = new Message();msg.what = 0x1233;Bundle bundle = new Bundle();bundle.putInt(UPPER_NUMBER,Integer.parseInt(et_digit.getText().toString()));msg.setData(bundle);calThread.handler.sendMessage(msg);}class CalThread implements Runnable {public Handler handler;@Overridepublic void run() {//1、調(diào)用 Looper的prepare()方法為當(dāng)前線程創(chuàng)建Looper對象,創(chuàng)建Looper對象時,它的構(gòu)造器會創(chuàng)建與之配套的MessageQueueLooper.prepare();handler = new Handler() {// 2、有了Looper之后,創(chuàng)建Handler子類的實(shí)例,重寫HandlerMessage()方法,該方法負(fù)責(zé)處理來自其它線程的消息。@Overridepublic void handleMessage(Message msg){if(msg.what == 0x1233){int upper = msg.getData().getInt(UPPER_NUMBER);List<Integer> nums = new ArrayList<Integer>();// 計算從2開始、到upper的所有質(zhì)數(shù)outer:for (int i = 2 ; i <= upper ; i++){// 用i處于從2開始、到i的平方根的所有數(shù)for (int j = 2 ; j <= Math.sqrt(i) ; j++){// 如果可以整除,表明這個數(shù)不是質(zhì)數(shù)if(i != 2 && i % j == 0){continue outer;}}nums.add(i);}// 使用Toast顯示統(tǒng)計出來的所有質(zhì)數(shù)Toast.makeText(MainActivity.this , nums.toString(), Toast.LENGTH_LONG).show();}}};//調(diào)用Looper的loop()方法啟動Looper。Looper.loop();} } }<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" ><EditTextandroid:id="@+id/et_digit"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="@string/limit" /><Button android:id="@+id/bt_prime"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/cal"android:onClick="cal"android:layout_below="@id/et_digit" /></RelativeLayout>
參考?xì)w檔代碼HandlerDemo1
總結(jié)
以上是生活随笔為你收集整理的Android中的消息机制:Handler消息传递机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于LayoutParams
- 下一篇: android sina oauth2.