關於handler的一些知識:
1、handler主要是用於主線程和子線程之間的通信,由於android在主線程之外的線程中不能操作UI,如果想要在子線程中改變UI,就需要使用handler。
2、handler可以想象成一個郵差,每天從Looper(消息循環,可以理解成郵政局)裏取得含有消息的信件,然後交給線程處理。
3、每個線程僅有一個Looper,但可以有多個handler。
4、handler在哪個線程創建,就對應於哪個線程的Looper。用哪一個handler發送的消息,消息就會發送到該handler對應的Looper裏。
5、創建handler前,必須先開啓Looper,由於主線程在創建時默認已經開啓了Looper,所以在主線程創建handler時中不需要開啓Looper,但在子線程中必須要先Looper.prepare(),再創建handler,最後還要Looper.loop()。
下面通過一個小例子來練習一下handler在主線程和子線程中通信、改變UI的用法。
新建一個android工程,不需要改變main.xml文件,新建一個HandlertestActivity,其中代碼如下:
package com.stormwy;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.Toast;
//練習在子線程中發送消息更新UI界面,以及主線程中發送消息給子線程。
//想要達到的效果:主線程接收到子線程的消息後,顯示一個alertdialog,
//然後如果選擇"YES",主線程就發送一個消息給子線程。
//子線程接收到主線程的決定後,發回一個反饋消息給主線程。最後主線程UI界面提示子線程的反饋消息。
public class HandlertestActivity extends Activity {
/** Called when the activity is first created. */
Handler handler;
Handler wife_handler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
handler = new Handler()
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == 1)
{
wife_handler = (Handler)msg.obj; //接受傳進來的子線程handler
AlertDialog.Builder builder = new AlertDialog.Builder(HandlertestActivity.this);//新建一個Alertdialog的builder
builder.setTitle("子線程說:");
builder.setMessage("你愛我嗎?");
builder.setIcon(R.drawable.ic_launcher);
builder.setPositiveButton("愛你",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Message backmsg = Message.obtain();
backmsg.what = 2;
wife_handler.sendMessage(backmsg);//用子線程handler發送消息到子線程的looper
}
});
builder.setNegativeButton("不愛",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Message backmsg = Message.obtain();
backmsg.what = 4;
wife_handler.sendMessage(backmsg);//用子線程handler發送消息到子線程的looper
}
});
builder.create();
builder.show();
}
if(msg.what == 3 || msg.what == 5)
{
Toast.makeText(HandlertestActivity.this, "子線程說:"+msg.obj, 1000).show();
}
}
};
WifeThread thread = new WifeThread(handler); //創建一個WifeThread子線程對象
thread.start(); //開啓線程
}
public class WifeThread extends Thread{
Handler uihandler;
Handler wifehandler;
public WifeThread(Handler handler) {
uihandler = handler; //利用構造函數接受主線程的handler,由於是內部類,其實直接用主線程的handler也可以。
}
public void run() {
super.run();
Looper.prepare(); //Android中,新建的線程默認是沒有looper的,所以創建handler之前必須要先創建線程的Looper對象
wifehandler = new Handler()
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == 2)
{
Message feedbackmsg = Message.obtain();
feedbackmsg.what = 3;
feedbackmsg.obj = "我也愛你!";
uihandler.sendMessage(feedbackmsg);//使用主線程的handler發送消息到主線程的looper
}
if(msg.what == 4)
{
Message feedbackmsg = Message.obtain();
feedbackmsg.what = 5;
feedbackmsg.obj = "好傷心啊";
uihandler.sendMessage(feedbackmsg);//使用主線程的handler發送消息到主線程的looper
}
}
};
Message sendmsg = Message.obtain();
sendmsg.what = 1;
sendmsg.obj = wifehandler; //利用Message.obj把子線程的handle傳遞給主線程。
uihandler.sendMessage(sendmsg);
Looper.loop(); //Looper好像一定要放在最後纔有效。
}
}
}