由于Android平台不允许Activity新启动的线程访问该Activity里的界面控件,这样就会导致新启动的线程无法动态改变界面控件的属性值。但在实际Android应用开发中,尤其是涉及动画的游戏开发中,需要让新启动的线程周期性地改变界面控件的属性值,这就需要借助Handler的消息传递机制实现。
一、Handler类简介
1.功能
Handler类主要有两个作用
(1)在新启动的线程中发送消息;
(2)在主线程中获取消息、处理消息。即当需要界面发生变化的时候,在子线程中调用Handler类的sendEmptyMessage()方法或sendMessage方法来发送消息到Handler。为了让主线程能"适时"地处理新启动的线程所发送的消息,可采用回调的方式来实现--只需重写Handler类中处理消息的方法,当新启动的线程发送消息时,Handler类中处理消息的方法会被自动调用。
2.Hnadler类常用方法
方法 | 描 述 |
public void handleMessage (Message msg) | 通过该方法获取、处理消息 |
public final boolean sendEmptyMessage (int what) | 发送一个只含有what标记的空消息 |
public final boolean sendMessage (Message msg) | 发送消息到Handler,通过handleMessage()方法接收和处理 |
public final boolean hasMessages (int what) | 监测消息队列中是否包含标记为what的消息 |
public final boolean post (Runnable r) | 将一个线程对象添加到消息队列 |
(1)创建一个Handler类对象,并重写handleMessage()方法(用于获取、处理消息);
(2)在新启动的线程中,调用Handler对象的发送消息方法;
(3)利用Handler对象的handleMessage()方法接收消息,然后根据不同的消息执行不同的操作。
注意:发送和处理消息的是同一Handler对象,即自己发送,自己处理。
三、源码实战
实现:实现一个动态变化的随机数效果。
(1)HandlerTest.java
package com.example.android_handler;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.widget.TextView;public class HandlerTest extends Activity { int i=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final TextView text = (TextView)findViewById(R.id.random); //1.创建一个Handler类对象,并重写handleMessage()方法 final Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what==0x520) { text.setText("获得的新随机数为:\n"+Math.random()); } } }; //2.定义一个计时器,让该计时器以1.2s周期性地执行指定任务(毫秒为基本单位)// new Timer().schedule(new TimerTask(){// public void run() {// handler.sendEmptyMessage(0x520);// }// }, 0, 1200); new Thread(new Runnable(){ public void run() { while(true) { try { Thread.sleep(1200); } catch (Exception e) { e.printStackTrace(); } handler.sendEmptyMessage(0x520); } } }).start(); }}
(2)layout/main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/random" android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="35dp" android:layout_gravity="center"/></LinearLayout>
效果演示:


源码分析:通过以上实例,我们知道在子线程发送消息时可以采用两种方法
a.定时器
new Timer().schedule(new TimerTask()
{
public void run()
{
......功能代码.....
}
}
b.子线程延时
new Thread(new Runnable()
{
public void run()
{
while(true)
{
Thread.sleep(1200);
......功能代码.....
}
}
}).start();
该方法有两点需要注意,一是如果希望程序不停的发送消息,则需要通过while(true)将功能代码包括起来;二是当子线程创建成功后,需要调用Thread的start()方法来启动该子线程。