您的位置:首页 > 移动开发 > Android开发

Android学习之问题处理程序Handler

2012-05-30 15:26 393 查看
Handler是Android中的问题处理程序,它处理接收到的信息和执行传递的Runnable对象。当你在创建一个Handler对象时,系统会随之创建一个和该对象绑定在一起的一个线程信息的队列,Handler会将信息和Runnable对象传递给该队列并在它们出队列的时候执行它们。可以将Handler理解为一个消息队列,在满足条件的情况下会处理相应的消息。

1.使用Handler 发送和处理消息

下图说明了Handler的操作过程,如图所示:



下述几个方法可以向Handler传递一个Message,会调用Handler的handleMessage(Message)方法接收并处理它们,这也必须要继承Handler重写它的handleMessage(Message)方法。如果不想继承Handler,也可以实现它的一个内嵌接口Handler.Callback。

sendEmptyMessage(int),

sendMessage(Message),

sendMessageAtTime(Message,long),

sendMessageDelayed(Message,long),

Message是一个包含了一些描述和随意数据的可以发送给Handler的对象,它包含的两个整型字段arg1、arg2和obj对象,在很多时候你可以不用理会它们,不做任何分配都是可以的。What字段是用户自定义的值,用来标识Message,这个字段是最有用的字段。如果想传送有内容的Message,就可能需要使用setData(Bundle data) 方法,来通过一个Bundle对象给它设置内容。说到这里也有必要说一下Bundle ,它其实就是一个Map,包含了一些键值对。下面给出一个处理Message的Handler示例:

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button android:text="SendEmptyMessage" android:id="@+id/send"
android:layout_width="wrap_content" android:layout_
height="wrap_content">
</Button>
<Button android:text="SendMessage" android:id="@+id/send2"
android:layout_width="wrap_content" android:layout_
height="wrap_content">
</Button>
</LinearLayout>
这段代码定义了两个按钮,名字是SendEmptyMessage和SendMessage,将会通过对他们的点击处理来触发不同的发送Message的方法,给Handler发送Message。

下面这段代码定义了一个名字为HandlerDemo的Activity,在其中创建了一个Handler的实例,并重写它的public void handleMessage(Message msg)方法来接收处理两种不同的Message。

Handler.java

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class HandlerDemo extends Activity {
//创建了一个Handler并实现其handlerMessage方法来处理其发出的消息
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
System.out.println(msg.what);
//获取消息的类型what来处理消息
switch (msg.what) {
case 0:
Toast t1 = Toast.makeText(HandlerDemo.this,
"SendEmptyMessage",
Toast.LENGTH_SHORT);
t1.show();
break;
case 1:
Bundle b = msg.getData();
Toast t2 = Toast.makeText(HandlerDemo.this,
"SendMessage:"
+ b.get("name") + "," + b.get("tel"),
Toast.LENGTH_SHORT);
t2.show();
System.out.println(b.get("name"));
break;
}
super.handleMessage(msg);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//初始化两个按钮,并设置其监听事件,使用这两个按钮来给Hanlder发送消息
Button send = (Button) findViewById(R.id.send);
Button send2 = (Button) findViewById(R.id.send2);
send.setOnClickListener(listener);
send2.setOnClickListener(listener);
}
OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.send:
//使用Handler的方法发送一个空消息指令,指令的值为0
handler.sendEmptyMessage(0);
break;
case R.id.send2:
//使用Handler发送一个Message,并在Message中附带资料
Message msg = new Message();
msg.what = 1;
Bundle b = new Bundle();
b.putString("name", "peiandsky");
b.putString("tel", "136********");
msg.setData(b);
if (handler.sendMessage(msg)) {
System.out.println("send success");
} else {
System.out.println("send fail");
}
break;
}
}
};
}
首先通过findViewById找到两个Button对象,并为他们设定监听事件。在监听器OnClickListener的实例listener 中根据不同按钮的按下发送不同的Message。

第一种为空的不带数据的Message,只传送了一个what的值来标识Message,在public void handleMessage(Message msg)方法中处理这个Message的时候就可以通过what来识别如何去做详细处理。

第二种是带有数据的Message,Message中附带了两个字符串的值,一个是姓名,一个是电话,也给这个Message设置了一个自己的what来标识它。

以上两种Message在处理的时候都会通过Toast来展示具体的处理数据。

sendMessageAtTime(Message,long)表示处理Message的时间在给定的时间点long时,再处理这个Message。

sendMessageDelayed(Message, long)则表示接收到Message后再过long毫秒后再执行处理这个Message。

2.用Handler 处理Runnable 对象

Handler操作的对象是实现Runnable类型的对象。

● post(Runnable)——立即执行runnable的run方法

● postAtTime(Runnable,long)——在指定的时间执行runnable的run方法

● postDelayed(Runnable,long)——延迟一定的时间再执行执行runnable的run方法

上述3个方法是Handler对Runnable对象的一些处理,它们将这些对象传入到队列里,在条件满足的时候会出队列,开启线程执行它们。

这和java中的计时器Timer和计时器任务TimerTask很类似。Handler对Runnable的处理和计时器对计时器任务的处理操作方式一致。

下述代码涵盖了对于Handler传递Runnable对象的使用,只需要稍微一改动,就可以将Handler当做线程来使用。在游戏中的体现比如说不停刷新屏幕,游戏元素的动画实现等,都离不开线程的使用。

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
public class HandlerDemo2 extends Activity {
//创建Handler实例
Handler handler = new Handler();
//创建3个Runnable对象的实例,分别为runnable1、runnable2和runnable3
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("post:" + System.currentTimeMillis());
}
};
Runnable runnable2 = new Runnable() {
@Override
public void run() {
System.out.println("postDelayed:" + System.currentTimeMillis());
}
};
Runnable runnable3 = new Runnable() {
@Override
public void run() {
System.out.println("postAtTime:" + System.currentTimeMillis());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在程序开始运行时使用handler执行3个runnable
handler.post(runnable1);
handler.postDelayed(runnable2, 1000);
handler.postAtTime(runnable3, 5000);
}
}
再来对代码进行一些改动:

Handler handler = new Handler();
Runnable runnable1 = new Runnable() {
@Override
public void run() {
//游戏逻辑,绘图不断刷新屏幕等操作
//延迟一段时间后调用自身,形成无限递归操作
handler.postDelayed(runnable1, 100);
System.out.println("game thread");
}
};
做出改动后,你会发现game thread在每隔100毫秒后就会自动打印一次,重复执行,就可以当做线程来使用了。这也是Handler的另一个比较重要的用途。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐