Handler机制的简单原理

Handler机制的简单原理



因为android UI界面不是线程安全的,不允许子线程更新主UI线程,为了达到主界面的更新操作,此时便有了Handler对象.

Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。Android利用Handler来实现UI线程的更新的。

HandlerAndroid中的消息发送器,其在哪个Activity中创建就属于且紧紧属于该Activity。还可以说其在哪个线程中new的,就是那个线程的Handler

 

Handler的定义主要接受子线程发送的数据并用此数据配合主线程更新UI. 



在UI线程

handler对象首先在主界面中进行声明,并覆盖其中的handleMessage(msg)方法。该方法用来接收子线程传递来的Message对象。




在子线程:

子线程启动后,首先创建Message对象。然后将待发送的数据放入Message对象中,并使用handler的sendMessage(msg)来发送msg对象,发送成功够,handleMessage(msg)拿到msg对象,并用这个msg对象里面的数据 来在主线程中更新手机界面。


Handler特点 :

 

handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程), 

它有两个作用:

(1)安排消息或Runnable在某个主线程中某个地方执行

(2)安排一个动作在不同的线程中执行 

 

Handler中分发消息的一些方法 

post(Runnable) 

postAtTime(Runnable,long) 

postDelayed(Runnable long) 

sendEmptyMessage(int) 

sendMessage(Message) 

sendMessageAtTime(Message,long) 

sendMessageDelayed(Message,long) 

sendMessage类方法,允许你安排一个带数据的Message对象到队列中,等待更新.

比如看看一般欢迎界面的实现方法:


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;

public class WelcomeScreen extends Activity{
	@Override
	protected void onCreate(Bundle savedInstanceState) {		
		super.onCreate(savedInstanceState);
		setContentView(R.layout.welcome_screen);

		Handler handler = new Handler();
		handler.postDelayed(new Loading(), 2000);//2s后执行Loading线程,  跳转到MainActivity
	}

	class Loading implements Runnable{
		@Override
		public void run() {
			// TODO Auto-generated method stub
			
			startActivity(new Intent(WelcomeScreen.this,MainActivity.class));
			WelcomeScreen.this.finish();
		}
	}
	
}


补充别人总结的:

1、向哪个Handler发送消息,就必须在哪个handler里面接收;

2、直接使用JAVA Thread是无法更新Android UI的,因为Android View在设计的时线程是不完全的,不过Android提供了几种供开发者在线程中更新UI的方法,如下:

runOnUiThread( Runnable )

post( Runnable )

postDelayed( Runnable, long )

3、直接使用hanlder.post等方法是在当前主线程里面做操作,而不是另外新建线程,建议使用Thread线程直接新建另外一个线程或者使用HandlerThread类也可以。(这句话的意思是ui线程是主线程,把一些耗时的操作放入其他线程做,主线程仅仅更新视图)

4、记住消息队列的先进先出原则。 






需要注意的:

 

. HandlerThread的区别。

 

Handler与调用者处于同一线程,如果Handler里面做耗时的动作,调用者线程会阻塞。Android UI操作不是线程安全的,并且这些操作必须在UI线程中执行。Android提供了几种基本的可以在其他线程中处理UI操作的方案,包括ActivityrunOnUiThread(Runnable),Viewpost以及1.5版本的工具类AsyncTask等方案都采用了HandlerHandlerpost对线程的处理也不是真正start一个新的线程,而是直接调用了线程的run方法,这正是google煞费苦心搞一套Handler的用意。

 

.Handler对于Message的处理不是并发的

 

一个Looper只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的。但是如果用不同的Looper则能达到并发的目的。Service中,onStart的执行也是阻塞的。如果一个startServiceonStart执行完成之前,再次条用startService也会阻塞。如果希望能尽快的执行onStart则可以在onStart中使用handler,因为Messagesend是非阻塞的。如果要是不同消息的处理也是并发的,则可以用不同的Looper实例化Handler

 

资源回收

Handler对象发送类似new Message ()形式的空Message可以达到清空Message的目的,这种做法与getLooper().quit()的做法是一样的。如果利用的资源较多,应及时清理。


 

Android中实现view的更新有第二种方法:


Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。

 Android程序中可以使用的界面刷新方法有两种,分别是利用Handler和利用postInvalidate()来实现在线程中刷新界面。
1,利用invalidate()刷新界面
  实例化一个Handler对象,并重写handleMessage方法调用invalidate()实现界面刷新;而在线程中通过sendMessage发送界面更新消息。

2,使用postInvalidate()刷新界面

使用postInvalidate则比较简单,不需要handler,直接在线程中调用postInvalidate即可。

程序如下:

   /**
       *    1 利用invalidate()刷新界面  
       *    实例化一个Handler对象,并重写handleMessage方法.
       *    调用invalidate()实现界面刷新;
       *    而在线程中通过sendMessage发送界面更新消息。 
       *    
       */

      // 在onCreate()中开启线程
        new Thread(new GameThread()).start();
        
     // 实例化一个handler

        Handler myHandler = new Handler() {
	        // 接收到消息后处理
	        public void handleMessage(Message msg) {
		        switch (msg.what) {
			        case Activity01.REFRESH: mGameView.invalidate(); // 刷新界面
			        break;
		        }
		        super.handleMessage(msg);
	        }
        }; 
        
    }
    
    class GameThread implements Runnable {
        public void run() {
	        while (!Thread.currentThread().isInterrupted()) {
		        Message message = new Message();
		        message.what = Activity01.REFRESH;
		        // 发送消息
		        Activity01.this.myHandler.sendMessage(message);
		        try {
		        	Thread.sleep(100);
		        } catch (InterruptedException e) {
		        	Thread.currentThread().interrupt();
		        }
	        }
        }
    }
    
    
    //2,使用postInvalidate()刷新界面 
   // 使用postInvalidate则比较简单,不需要handler,直接在线程中调用postInvalidate即可。 

    class GameThread2 implements Runnable { 
	    public void run() { 
		    while (!Thread.currentThread().isInterrupted()) { 
			    try { 
			    	Thread.sleep(100); 
			    } catch (InterruptedException e) { 
			    	Thread.currentThread().interrupt(); 
			    } 
			    // 使用postInvalidate可以直接在线程中更新界面 
			    mGameView.postInvalidate(); 
		    } 
	    } 
    }
 







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章