handler类允许你发送消息和处理线程消息队列中的消息及runnable对象。handler实例都是与一个线程和该线程的消息队列一起使用,一旦创建了一个新的handler实例,系统就把该实例与一个线程和该线程的消息队列捆绑起来,这将可以发送消息和runnable对象给该消息队列,并在消息队列出口处处理它们。
handler类有两种主要用途:
1、按照时间计划,在未来某时刻,对处理一个消息或执行某个runnable实例。
2、把一个对另外线程对象的操作请求放入消息队列中,从而避免线程间冲突。
时间类消息通过如下方法使用:
post(Runnable)
postAtTime(Runnable, long)
postDelayed(Runnable, long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message, long)
andsendMessageDelayed(Message, long)
methods. post之类函数可以传输一个runnable对象给消息队列,并在到达消息队列后被调用。sendmessage之类函数可以传送一个包含数据的message对象,该message对象可以被Handler类的handleMessage(Message) 方法所处理。
post之类函数和sendmessage之类的函数都可以指定消息的执行时机,是立即执行、稍后一段时间执行,还是在某个确定时刻执行。这可以用来实现超时、消息或其他时间相关的操作。
当一个进程启动时,主线程独立执行一个消息队列,该队列管理着应用顶层的对象(如:activities、broadcast receivers等等)和所有创建的窗口。你可以创建自己的一个线程,并通 过handler来与主线程进行通信。这可以通过在 新的线程中调用主线程的handler的post和sendmessage操作来实现。
Handler类主要可以使用如下3个方法来设置执行Runnable对象的时间:
- //立即执行Runnable对象
- public final boolean post(Runnable r);
- //在指定时间uptimeMillis 后执行Runnable对象
- public final boolean postAtTime(Runnable r,long uptimeMillis);
- //在指定的时间间隔delayMillis 执行Runnable对象
- public final boolean postDelayed(Runnable r,long delayMillis);
从上面的三个方法可以看出,第一个参数的类型都是Runnable ,因此,在调用这三个方法之前,需要有一个实现Runnable接口的类,Runnable接口的代码如下:
- public interface Runnable
- {
- public voic run();//线程要执行的方法
- }
在Runnable接口中只有一个Run 方法,该方法为线程执行方法。
- Handler handler = new Handler();
- handler.postDelayed(This,5000);
- handler.removeCallbacks(this);
除此之外还可以用postAtTime方法指定未来的某一个精确时间来执行Runnable对象,代码如下:
- Handler handler=new Handler();
- handler.postAtTime(new RunToast(this){ },android.os.SystemClock.uptimeMillis()+15*1000);//在15秒后执行Runnable对象
- class RunToast implements Runnable
- {
- private Context context;
- public RunaToast(Context context)
- {
- this.context;
- }
- @Override
- public void run()
- {
- Toast.makeText(context,"15秒后显示Toast提示信息",Toast.LENGTH_LONG).show();
- }
- }
要注意的是,不管使用哪个方法来执行Runnable对,都只能运行一次。如果想循环执行,必须在执行完后再次调用post、postAtTime或postDelayed方法。
例如,在Run方法中再次调用postDelayed方法,代码如下:
- public void run()
- {
- tvCount.setText("Count:" + String.valueOf(++count));
- //现次调用postDelayed方法,5秒后run方法仍被调用,然后再一次同用postDelayed方法,这样就行成了循环调用
- handler.postDelayed(this, 5000);
- }
完整代码如下:HandlerTestActivity.java
package com.android.sky.demo.handler;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class HandlerTestActivity extends Activity implements OnClickListener, Runnable {
/** Called when the activity is first created. */
private static final String TAG = "HandlerTestActivity";
private Handler mHandler;
private Button btnStart;
private Button btnStop;
private Button btnShowToast;
private TextView tvCount;
private int count = 0;
class RunToast implements Runnable {
private Context context;
public RunToast(Context context) {
this.context = context;
}
@Override
public void run() {
Toast.makeText(context, "15秒后显示Toast提示信息", Toast.LENGTH_LONG)
.show();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnStart:
mHandler.postDelayed(this, 5000);
break;
case R.id.btnStop:
mHandler.removeCallbacks(this);
break;
case R.id.btnShowToast:
mHandler.postAtTime(new RunToast(this)
{ }, android.os.SystemClock.uptimeMillis() + 15 * 1000);
break;
}
}
@Override
public void run() {
tvCount.setText("Count:" + String.valueOf(++count));
mHandler.postDelayed(this, 5000);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViews();
setListeners();
mHandler = new Handler();
}
private void findViews() {
// TODO Auto-generated method stub
btnStart = (Button) findViewById(R.id.btnStart);
btnStop = (Button) findViewById(R.id.btnStop);
btnShowToast = (Button) findViewById(R.id.btnShowToast);
tvCount = (TextView) findViewById(R.id.tvCount);
}
private void setListeners() {
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
btnShowToast.setOnClickListener(this);
}
}
布局文件代码如下: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">
<TextView
android:id="@+id/tvCount"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20dp" />
<Button
android:id="@+id/btnStart"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn_start" />
<Button
android:id="@+id/btnStop"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn_stop" />
<Button
android:id="@+id/btnShowToast"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn_showToast" />
</LinearLayout>
资源文件代码如下 strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, HandlerTestActivity!</string>
<string name="app_name">HandlerTest</string>
<string name="btn_start">开始计数</string>
<string name="btn_stop">停止计数</string>
<string name="btn_showToast">15秒后显示Toast信息框</string>
</resources>