Handler用于线程间的通信,本文分析Handler、Looper、MessageQueue等的原理及Handler和BroadcastReceiver的差异。
线程A创建Looper及MessageQueue,创建Handler;在线程B创建消息,用Handler将消息PUSH给由Looper管理的MessageQueue;线程A通过Looper循环查询MessageQueue,发现消息则POP给Handler处理。
1、示例分析
1) MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
public static final int MSG_FIRST = 0x01;
public static final int MSG_SECOND = 0x02;
public static final int MSG_THIRD = 0x03;
public static final int MSG_FOURTH = 0x04;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Handler mHandler = new Handler(){
@Override
public void dispatchMessage(Message msg) {
Log.i(TAG, "dispatchMessage-"+msg.what);
// super.dispatchMessage(msg);
if(handler_sub!=null)
handler_sub.dispatchMessage(msg);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case MSG_FIRST:
Log.i(TAG, "MSG_FIRST");break;
case MSG_SECOND:
Log.i(TAG, "MSG_SECOND");break;
}
}
};
private class MyThread extends Thread{
int mId = 0;
public MyThread(int id){
mId = id;
}
@Override
public void run() {
super.run();
//global message pool
switch(mId){
case 0:
mHandler.obtainMessage(MSG_FIRST).sendToTarget();break;
case 1:
Message msg = new Message();
msg.what = MSG_SECOND;
mHandler.sendMessageDelayed(msg, 5000L);
// mHandler.sendMessageAtTime(msg, SystemClock.uptimeMillis()+5000L);
// mHandler.sendMessageAtFrontOfQueue(msg);
// mHandler.sendMessage(msg);
break;
case 2:
Message.obtain(mHandler, MSG_THIRD).sendToTarget();
// Message.obtain(mHandler, MSG_THIRD, 1, 2, null).sendToTarget();
}
}
}
public void onClick(View v){
switch(v.getId()){
case R.id.btn:
MyThread myThread = new MyThread(0);
myThread.start();break;
case R.id.btn2:
MyThread myThread1 = new MyThread(1);
myThread1.start();break;
case R.id.btn3:
MyThread myThread2 = new MyThread(2);
myThread2.start();break;
case R.id.btn4:
MyThread2 mt = new MyThread2();
mt.start();
}
}
Handler handler_sub;
private class MyThread2 extends Thread{
@Override
public void run() {
super.run();
Looper.prepare();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
TextView tv = (TextView) findViewById(R.id.txt);
tv.setText("less popular");
}
}, 3000L);
handler_sub = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG, "handleMessage-"+Thread.currentThread().getName()+"|"+msg.what);
}
};
Looper.loop();
Looper.myLooper().quitSafely();
}
}
}
2) activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="send"/>
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="send2"/>
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="send3"/>
<Button
android:id="@+id/btn4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="send4"/>
<TextView
android:id="@+id/txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
2、Handler和BroadcastReceiver的比较
差异:发消息需要Handler引用,而发广播只需提供ACTION;发前后Message和Object还是同一个对象,Intent和Bundle已是另一个对象。
1) MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction(MyBroadcastReceiver.ACTION_RABBIT);
registerReceiver(receiver, filter);
}
protected void onDestroy() {
Log.i(TAG, "onDestroy");
super.onDestroy();
unregisterReceiver(receiver);//注销所有ACTION
};
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
//Message和Person对象不变
Log.w(TAG, "handleMessage-msg:"+msg.hashCode());
Log.w(TAG, "handleMessage-Person:"+msg.obj.hashCode());
break;
default:
break;
}
};
};
public void onClick(View v){
switch (v.getId()) {
case R.id.btn:
Person p = new Person();
p.setName("talent");
p.setAge(21);
Log.w(TAG, "onClick-Person:"+p.hashCode());
Message msg = mHandler.obtainMessage(0, p);
Log.w(TAG, "onClick-msg:"+msg.hashCode());
msg.sendToTarget();
break;
case R.id.btn_broadcast:
//Intent和Bundle均是Parcelable、Cloneable的子类
Intent intent = new Intent();
intent.setAction(MyBroadcastReceiver.ACTION_RABBIT);
Bundle bundle = new Bundle();
Log.w(TAG, "onClick-Bundle:"+bundle.hashCode());
Log.w(TAG, "onClick-Intent:"+intent.hashCode());
bundle.putBoolean("ready", true);
intent.putExtras(bundle);//intent.removeExtra(String);
sendBroadcast(intent);
break;
default:
break;
}
}
}
2) activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="tap me"/>
<Button
android:id="@+id/btn_broadcast"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="send broadcast"/>
</LinearLayout>
3) Person.java
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
4) MyBroadcastReceiver.java
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = MyBroadcastReceiver.class.getSimpleName();
public static final String ACTION_RABBIT = "action.rabbit";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();//set/get
if(ACTION_RABBIT.equals(action)){
Bundle bundle = intent.getExtras();//put/get
//传过来的Intent和Bundle对象均已变
Log.w(TAG, "onReceive-Bundle:"+bundle.hashCode());
Log.w(TAG, "onReceive-intent:"+intent.hashCode());
}
}
}