1.UI线程中Handler 向 UI 线程Looper的MessageQueue发送消息,并接收消息处理
2.子线程向UI线程发送消息。(子线程获取UI线程的looper,并通过handler向其发送消息)
3.UI线程向子线程发送消息。(UI线程通过子线程handler的一个引用,向其looper发送消息)
package com.jerry.test;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
//布局参数
private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
private final int MP = LinearLayout.LayoutParams.MATCH_PARENT;
//显示UI
private TextView tv;
//用于主线程内部消息和子线程向主线程发起消息的handler
private EventHandler mHandler;
//handler用以给子线程发送消息,在这里创建是为了方便主线程引用
private Handler mHandler2;
//
private Button btn1, btn2 ,btn3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initUI();
//开启用以接受主线程消息的子线程
new Thread(new Runnable() {
@Override
public void run() {
//创建此子线程的looper
Looper.prepare();
mHandler2 = new Handler(){
public void handleMessage(Message msg) {
Log.i("jerry","message is : " + msg.obj);
}
};
//looper处理事务,looper.loop()之后的代码不会执行。
//因为Looper的事件处理方法是循环的,执行完后会返回最开始进行消息监听
//想要退出looper循环,需要执行Looper.myLooper().quit();
Looper.loop();
}
}).start();
}
/**
* 初始化界面UI
*/
private void initUI() {
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn1 = new Button(this);
btn1.setId(101);
btn1.setText("test looper");
btn1.setOnClickListener(this);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(500, 80);
param.topMargin = 10;
layout.addView(btn1, param);
btn2 = new Button(this);
btn2.setId(102);
btn2.setText("test looper 2");
btn2.setOnClickListener(this);
layout.addView(btn2, param);
btn3 = new Button(this);
btn3.setId(103);
btn3.setText("test looper 3");
btn3.setOnClickListener(this);
layout.addView(btn3, param);
tv = new TextView(this);
tv.setTextColor(Color.WHITE);
tv.setText("");
LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(MP,WC);
param2.topMargin = 10;
layout.addView(tv, param2);
setContentView(layout);
}
@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;
}
class EventHandler extends Handler {
public EventHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
tv.setText((String) msg.obj);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//主线程中发送消息
case 101:
//程序启动时,主线程已创建了一个looper对象,并且有一个MessageQueue
//Looper.myLooper static 方法获取当前线程中的looper对象。
Looper looper = Looper.myLooper();
//实例化handler,用以与looper沟通,activity等可以通过handler将message传递给looper,
//looper会将获得的message放入到该looper的MessageQuere(消息队列)中。
//handler也是一个message监听,用以接受处理looper发出的消息。
mHandler = new EventHandler(looper);
//清除整个messageQueue中的事件,确保不会通知到别人
mHandler.removeMessages(0);
//message内容
String obj = "This is Jerry's message!";
//封装成message
Message m = mHandler.obtainMessage(1, obj);
//发送
mHandler.sendMessage(m);
//通过handler将message放入了初始化时引用的looper的MessageQueue中。
//looper发现MessageQueue中有消息,就将它广播出去。handler接受到此消息,调用handleMessage处理
break;
case 102:
//由子线程发送消息给主线程
new Thread(new Runnable() {
@Override
public void run() {
Looper myLooper,mainLooper;
//获取当前线程looper
myLooper = Looper.myLooper();
//获取主线程looper
mainLooper = Looper.getMainLooper();
String obj;
if(myLooper == null){
mHandler = new EventHandler(mainLooper);
obj = "current thread has no looper";
}else{
mHandler = new EventHandler(myLooper);
obj = "this is from current thread";
}
mHandler.removeMessages(0);
Message message = mHandler.obtainMessage(101, obj);
mHandler.sendMessage(message);
}
}).start();
break;
case 103:
//主线程发送消息给子线程
String message = "this is a message from main thread";
Message msg = mHandler2.obtainMessage(103, message);
mHandler2.sendMessage(msg);
break;
default:
break;
}
}
}