在Android中主线程与子线的通信往往会使用到Handler,Looper,MessageQueen,Message。首先简单的来介绍下他们在通信之间中的作用,以及相关使用方法。
Handler:相当于消息队列中具体处理消息的工人。可以有多个
Looper:相当于消息队列中的管家。只有1个。
MessageQueen:存放消息的队列。
Message:传递信息的消息体
它就像一个消息队列(MessageQueue)的管家(Looper),一个消息队列只有一个管家,并且管理者整个消息队列,而一个消息队列内可以容纳多个消息(Message),而工人(Handler)也可以有多个,管家派遣他们向消息队列中存储或取出消息后执行任务;所以它们的个数如下:
管家(Looper): 1 个;
消息队列(MessageQueue):1 个;
消息(Message):可以多个;
工人(Handler):可以多个;
1. 主线程往子线程中发消息:
由于子线程中并没有消息队列,所以首先需要初始化消息队列(Looper.prepare()),以及启动消息循环(Looper.loop())。只有这样才能在子线程中使用Handler来捕获从主线程传过来的消息。详细的请看下面代码,实现了主线程发送一条消息到子线程,子线程接收到消息后将值用Toast显示出来。
1. package
2.
3. import
4. import
5. import
6. import
7. import
8. import
9. import
10. import
11. import
12. import
13.
14. public class TextActivity extends
15. /**
16. * 主线程发送消息到子线程
17. */
18. //主线程发送消息到子线程按钮
19. private Button mButton = null;
20. //子线程更新textView的值
21. private TextView mText = null;
22.
23. private int num = 0;
24.
25. @Override
26. protected void
27. super.onCreate(savedInstanceState);
28. super.setContentView(R.layout.text_layout);
29.
30.
31. mButton = (Button) findViewById(R.id.send_msg_sub_thread);
32. mText = (TextView) findViewById(R.id.update_text);
33.
34. final SubThread subThread = new
35. subThread.start();
36.
37. new
38.
39. @Override
40. public void
41. Message msg = Message.obtain();
42. msg.arg1 = num ;
43. subThread.subHandler.sendMessage(msg);
44. num ++;
45. }
46. });
47. }
48.
49.
50. private class SubThread extends
51. null;
52. @Override
53. public void
54. //初始化looper
55. Looper.prepare();
56. new
57. @Override
58. public void
59. this, "子线程收到消息:"
60. }
61. };
62. //启动消息循环
63. Looper.loop();
64. }
65. }
66. }
package com.vic.demo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class TextActivity extends Activity{
/**
* 主线程发送消息到子线程
*/
//主线程发送消息到子线程按钮
private Button mButton = null;
//子线程更新textView的值
private TextView mText = null;
private int num = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.text_layout);
mButton = (Button) findViewById(R.id.send_msg_sub_thread);
mText = (TextView) findViewById(R.id.update_text);
final SubThread subThread = new SubThread();
subThread.start();
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Message msg = Message.obtain();
msg.arg1 = num ;
subThread.subHandler.sendMessage(msg);
num ++;
}
});
}
private class SubThread extends Thread{
Handler subHandler = null;
@Override
public void run() {
//初始化looper
Looper.prepare();
subHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(TextActivity.this, "子线程收到消息:" + msg.arg1, Toast.LENGTH_SHORT).show();
}
};
//启动消息循环
Looper.loop();
}
}
}
代码执行结果如下图所示:
2. 子线程往主线程中发消息:
子线程往主线程中发送消息就比较简单了,因为在主线程中默认已经实现了消息队列。即已经实现了Looper.prepare()以及Looper.loop(),所以我们直接从子线程发送消息后,主线程用handler接收就可以了。下面的代码实现了在主线程中启动了一个子线程,子线程向主线程发送消息后,主线程更新textview的操作。
1. package com.vic.thread;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5. import android.os.Handler;
6. import android.os.Looper;
7. import android.os.Message;
8. import android.widget.TextView;
9.
10. import com.vic.demo.R;
11.
12. public class
13. private
14.
15. Handler mainHandler = null;
16. @Override
17. protected void
18. super.onCreate(savedInstanceState);
19. setContentView(R.layout.sub2main);
20. mText = (TextView) findViewById(R.id.main_text);
21. //子线程启动
22. new
23. //接收子线程发送过来消息,并更新UI
24. new
25. @Override
26. public void
27. super.handleMessage(msg);
28. "从子线程接收到的消息为:"
29. }
30. };
31. }
32.
33. class
34. @Override
35. public void
36. super.run();
37. Message msg = Message.obtain();
38. msg.arg1 = 1;
39. mainHandler.sendMessage(msg);
40. }
41. }
42.
43. }
package com.vic.thread;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.TextView;
import com.vic.demo.R;
public class Sub2MainThread extends Activity{
private TextView mText = null;
Handler mainHandler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sub2main);
mText = (TextView) findViewById(R.id.main_text);
//子线程启动
new SubThread().start();
//接收子线程发送过来消息,并更新UI
mainHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mText.setText("从子线程接收到的消息为:" + msg.arg1);
}
};
}
class SubThread extends Thread{
@Override
public void run() {
super.run();
Message msg = Message.obtain();
msg.arg1 = 1;
mainHandler.sendMessage(msg);
}
}
}
代码执行结果如下
总结:android主线程与子线程之间的通信往往是通过handler,Looper以及message来实现的。关键在于如果线程中没有实现消息队列的机制,需要通过调用Looper.prepare()以及Looper.loop()来建立好消息传送的通道。而主线程默认已经实现了消息 队列的相关机制,就不需要再进行消息初始化的操作了,直接调用handler的handleMessage方法来处理从子线程传递过来的消息。