由于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()方法来启动该子线程。