从上面的解释可以看出来,Handler的作用是与一个线程绑定,之后就可以发消息给线程的消息队列来执行动作。
有两个主要的用途:
1、安排在不同事件执行什么动作。比如说我们要每隔几秒钟刷新一下Activity的title。
2、给另外线程发消息。
可以说,Handler是Runnable和Activity之间的桥梁。
下面看例子,这个例子中,每隔1s刷新一次title。
package com.example.testhandler;
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.view.Menu;
public class MainActivity extends Activity {
private static int count = 0;
private final Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
updateTitle();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Timer t = new Timer();
t.scheduleAtFixedRate(new MTask(), 1000, 1000);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private void updateTitle() {
this.setTitle("welcome " + count++);
}
class MTask extends TimerTask {
@Override
public void run() {
Message m = new Message();
m.what = 1;
myHandler.sendMessage(m);
}
}
}
Message中what参数的解释如下:
/**
* User-defined message code so that the recipient can identify
* what this message is about. Each {@link Handler} has its own name-space
* for message codes, so you do not need to worry about yours conflicting
* with other handlers.
*/
public int what;
用户用这个字段来区分发送过来的消息是什么消息,从而调用不同的方法来处理消息。在上面的例子中就是根据发送过来的what是不是1,来决定是否调用updateTitile方法。
---------------------------
再看下post方法:
post方法给关联的线程发送了一个Runable对象,加到其消息队列中。
看看下面的官方解释:
Scheduling messages is accomplished with the post(Runnable)
, postAtTime(Runnable, long)
, postDelayed(Runnable, long)
, sendEmptyMessage(int)
, sendMessage(Message)
, sendMessageAtTime(Message, long)
, andsendMessageDelayed(Message, long)
methods. The post versions allow you to enqueue Runnable objects to be called by the message queue when they are received; the sendMessage versions allow you to enqueue a Message
object containing a bundle of data that will be processed by the Handler's handleMessage(Message)
method (requiring that you implement a subclass of Handler).
从上面的解释看到,post***方法给消息队列添加Runnable对象。而sendMessage则可以消息队列发送一些数据。sendMessage发送的消息经由handler的handleMessage方法来处理。
所以,上面用sendMessgae来实现的例子,也可以用post方法来实现:
package com.example.testhandler;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
public class MainActivity extends Activity {
private int count = 0;
private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Timer t = new Timer();
t.scheduleAtFixedRate(new MyTask(), 1000, 1000);
}
private class MyTask extends TimerTask {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
updateTitle();
}
});
}
}
public void updateTitle() {
setTitle("Welcome " + count++);
}
}
只不过,post方法直接发送一个runnable对象给消息队列。不能带一些参数过去。而sendMessage可以做到这一点。
----------------------
当然,post()方法还有一些变体,比如postDelayed()、postAtTime()分别用来延迟发送、定时发送
---------------------------------
除了Handler,View也是有post方法的。
看下面的例子:
package com.example.posttest;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView view = (TextView) findViewById(R.id.text);
Button b = (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.e("mason", "go");
view.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Log.e("mason", "here");
view.setText("you great");
view.refreshDrawableState();
}
});
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
例子中,有一个TextView和一个Button。点击button的时候,textview发出一个消息,在消息中,开启一个线程更新textview的内容。
下面分析下View的post函数:
函数把参数runnable添加到UI线程的事件队列中。与Handler的作用一致。