Handler问题

•使用Handler是异步的,它会建立新线程么?

•Handler是在主线程内么?

Handler的post和sentMessage方法,使用的是一个队列还是两个?

  是一个队列,post是线程队列,sentMessage是消息队列

•子线程中建立一个handler,然后sendMessage会怎样?

子线程建立handler,构造的时候传入主线程的,Looper

•Handler是做什么的,既然是异步任务处理,他本身是多线程的么?

Handler作用
1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器
2)线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息。 当你创建子线程时,你可以在你的子线程中拿到父线程中创建的Handler对象,就可以通过向父线程的消息队列发送消息了。 由于Android要求在UI线程中更新界面,因此,可以通过该方法在其他线程中更新界面。

一、角色描述

2.Handle、 Looper 、Message Queue和线程之间的关系

1).Looper(相当于隧道)一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(车队、消息隧道).

  •当前线程中有一个Looper这样的循环在监听消息队列,但又不是额外的线程,这不是和我们的学习常理相勃吗?

Looper没有新开一个线程,Looper又系统来控制的循环。

2).Handler 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper(从Message Queue取出)所送来的消息.

3).Message Queue(消息队列): 用来存放线程放入的消息。

 4).线程: UI thread 通常就是main thread, 而Android启动程序时会替它建立一个Message Queue.

每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。

见下面两张图,你将明白Handler作用,.Message Queue,.Looper

3.主线程里面定义两个不同的handler实例,其中一个handler发出的消息另外一个能接收到吗?

    不能,虽然主线程共享同一个消息队列,但是它们通过message的what变量来区分到底是由哪一个handler发出的消息。Handler实例与消息处理是关联的,发送和接收要匹配

mainHandler2 = new Handler(){

			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				super.handleMessage(msg);//这里接收不到
				Toast.makeText(HandlerConceptActivity.this, "[Main Thread]Handler2 Get the message: "+msg.getData().getString(HANDLER_KEY), 5000).show()  ;
			}
			
		} ;
		mainHandler1 = new Handler(){

			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				super.handleMessage(msg);//这里能接收到
				Toast.makeText(HandlerConceptActivity.this, "[Main Thread]Handler1 Get the message: "+msg.getData().getString(HANDLER_KEY), 5000).show()  ;
			}
			
		} ;

		//Handler Lab1
		findViewById(R.id.buttonHandlerLab1).setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				new Thread(new Runnable(){

					@Override
					public void run() {
						// TODO Auto-generated method stub
						
						mainHandler1.sendMessage(defineNewMessage("Lab1")) ;
						//try to use mainHanlder2 to send meesage and receive . 
						//mainHandler2.sendMessage(defineNewMessage("Lab1")) ;
						
					}
					
				}).start() ;
			}
			
		}) ;

4.任何一个线程都有消息队列吗
     默认只有主线程才有消息队列,自己新建的普通线程是没有线程队列的。不过子线程中用HandlerThread,默认有消息队列
  1)//下面代码会抛出Can't create handler inside thread that has not called Looper.prepare()异常
            findViewById(R.id.buttonHandlerLab2).setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				new Thread(new Runnable(){

					@Override
					public void run() {
						Handler lab2Handler = new Handler()  ;
						lab2Handler.sendMessage(defineNewMessage("Lab2")) ;
                                              
					}
					
				}).start() ;
			}
		}) ;


2)下面的代码是正确的
       class SubHandlerThread extends HandlerThread{

		public SubHandlerThread(String name) {
			super(name);
			// TODO Auto-generated constructor stub
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			ProcessCaculate() ;
			Looper lp = this.getLooper() ;

			new Handler(lp){
				
				@Override
				public void handleMessage(Message msg) {
					// TODO Auto-generated method stub
					super.handleMessage(msg);
					Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message by HandlerThread "+ msg.getData().getString(HANDLER_KEY))  ;
				}
	        	
	        }.sendMessage(defineNewMessage("Lab2.2"))  ;
		}
		
	}






findViewById(R.id.buttonHandlerLab3).setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stub//using HandlerThread to make handler (message queue) ,send messageSubHandlerThread subHandlerThread = new SubHandlerThread("threadone"); subHandlerThread.start();}}) ;



5.子线程的handler可以使用主线程的消息队列吗
可以的。
//Handler Lab3.1 child thread get main thread's looper and send message .
		findViewById(R.id.buttonHandlerLab4).setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				new Thread(new Runnable(){
					
					@Override
					public void run() {
						// TODO Auto-generated method stub
						Handler lab3Handler  ;
						lab3Handler = new Handler(Looper.getMainLooper())
						{

							@Override
							public void handleMessage(Message msg) {
								// TODO Auto-generated method stub
								super.handleMessage(msg);
								Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message: "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler")  ;
							}
							
						};
						lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
						
					}
					
				}).start() ;
			}
			
		}) ;
5.子线程的handler可以使用子线程的消息队列吗
//Handler Lab3.2 using looper.prepare() and looper.loop()  .
		findViewById(R.id.buttonHandlerLab5).setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				new Thread(new Runnable(){
					
					@Override
					public void run() {
						Looper.prepare();//实例化looper对象,生成消息队列
						lab3Handler = new Handler(){

							@Override
							public void handleMessage(Message msg) {
								// TODO Auto-generated method stub
								super.handleMessage(msg);
								Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message from "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler")  ;
							}
						} ;
						
						lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
						Looper.loop() ;//循环消息队列
					}
					
				}).start() ;
			}
			
		}) ;
 

总结:
1.Handler实例与消息处理是关联的,发送和接收要匹配。
2.Handler操作队列,主要是在子线程操作主线程消息队列
3.子线程默认是没有消息队列的
原文地址:https://www.cnblogs.com/firecode/p/2460867.html