日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android中的消息机制:Handler消息传递机制

發(fā)布時間:2024/1/23 Android 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android中的消息机制:Handler消息传递机制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

參考《瘋狂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


2、在主線程中,系統(tǒng)已經(jīng)初始化了一個Looper對象,因此程序直接創(chuàng)建Handler即可。

package org.crazyit.event;import java.util.Timer; import java.util.TimerTask;import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.ImageView;/*** Description:* <br/>site: <a href="http://www.crazyit.org">crazyit.org</a>* <br/>Copyright (C), 2001-2014, Yeeku.H.Lee* <br/>This program is protected by copyright laws.* <br/>Program Name:* <br/>Date:* @author Yeeku.H.Lee kongyeeku@163.com* @version 1.0*/ public class HandlerTest extends Activity {// 定義周期性顯示的圖片的IDint[] imageIds = new int[]{R.drawable.java,R.drawable.ee,R.drawable.ajax,R.drawable.xml,R.drawable.classic};int currentImageId = 0;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);final ImageView show = (ImageView) findViewById(R.id.show);final Handler myHandler = new Handler(){@Overridepublic void handleMessage(Message msg){// 如果該消息是本程序所發(fā)送的if (msg.what == 0x1233){// 動態(tài)地修改所顯示的圖片show.setImageResource(imageIds[currentImageId++% imageIds.length]);}}};// 定義一個計時器,讓該計時器周期性地執(zhí)行指定任務(wù)new Timer().schedule(new TimerTask(){@Overridepublic void run(){// 發(fā)送空消息myHandler.sendEmptyMessage(0x1233);}}, 0, 1200);} }



總結(jié)

以上是生活随笔為你收集整理的Android中的消息机制:Handler消息传递机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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