在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显示出来。
- 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();
- }
- }
- }
- 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的操作。
- 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);
- }
- }
- }
- 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方法来处理从子线程传递过来的消息。