在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();
		}
	}	
}






代码执行结果如下图所示:


Android 子线程在那个周期中开启最好 android主线程和子线程通讯_主线程


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 子线程在那个周期中开启最好 android主线程和子线程通讯_子线程_02

总结:android主线程与子线程之间的通信往往是通过handler,Looper以及message来实现的。关键在于如果线程中没有实现消息队列的机制,需要通过调用Looper.prepare()以及Looper.loop()来建立好消息传送的通道。而主线程默认已经实现了消息 队列的相关机制,就不需要再进行消息初始化的操作了,直接调用handler的handleMessage方法来处理从子线程传递过来的消息。