Handler机制总结

     在异步更新UI时用到Hanler消息机制,笔者(新手)在深入过程的总结。              用到一下参数:

 

  Looper:
 
提供消息存储以及执行的一个类
           sThreadLocal.set(new Looper(quitAllowed)); 源码中的Looper类,进入后:
 
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } 这里通过私有方法创建了一个Looper,然后存放在sThreadLocal中。
sThreadLocal会根据不同线程依次保存这个Looper对象。
	          所以最终的Looper对象意义就是得到一个MessageQueue,以及标识当前线程。
  MessageQueue: 从上面方法中得到的。 从字面意思就是一个消息队列用于存储Handler发送的消息。
 
Handler:传递消息以及存放我们重写的代码,消息传递给MessageQueue,重写的代码在
public void handleMessage(Message msg) { }
  sMainLooper:本身也是Looper,但是在Activity生命周期中首先会生成它,其实就是主线程的Looper
		上面的Looper是子线程Looper。
  Messager:消息的实体,
message.Obj: 消息内部存放对象。 message.what:消息内部存放int值。 message.arg1:消息内部存放int值。
 
message.target:指代发送这个message的对象就是Handler,外部无法访问,在sendMessage()
			   方法中最终调用这个。看源码                
 
msg.target = this; this指的就是Handler本身。
                     message传递到MessageQueue(依赖一个线程不断运行)后同样可以访问内部对象,值。因此实现的Handler异步处理机制。
 
message.callback: 直接上源码:
public final boolean post(Runnable r){ return sendMessageDelayed(getPostMessage(r), 0);  }
		可看出我们传递的实现Runnable对象最终也被包装成一个Message对象。           
           private static Message getPostMessage(Runnable r) {
               Message m = Message.obtain();
               m.callback = r;
               return m;
			}  

可看出这个callback是用于Message内部一个用于保存实现Runnable对象的。

 
 
   Handler.mCallback:继续撸源码:	
public Handler(Callback callback) { this(callback, false); } Handler的构造函数的一个参数可以是CallBack对象,继续往下我们看到这句:
mCallback = callback; 也就是说Handler.mCallback其实就是我们传入的自定义Callback对象。
 
  		ok 用到的对象也差不多了 ,分析源码点到为止。 下面是方法。   go on!
 
 
 
 首先是常用的Handler的构造方法:
	 ONE:	
public Handler() { this(null, false); } 无参,这种会自动绑定到当前线程的Looper。进而绑定到消息队列。
mLooper = Looper.myLooper(); //我们上述说到的实例化Looper对象。
						     就是从sThreadLocal里拿Looper。
	
                    if (mLooper == null) {         //如果没有这个Looper就报错。
                        throw new RuntimeException(
                       "Can't create handler inside thread that has not called Looper.prepare()");
                            }
                       mQueue = mLooper.mQueue;	    //Looper里的MessageQueue	
                       mCallback = callback;        //这里的callback为null;
                       mAsynchronous = async;
 
TWO:
public Handler(Callback callback) { this(callback, false); } 
                        看到这是不是很简单了,这个与上面区别就是callback不为空了。
 
THERE:
public Handler(Looper looper) { this(looper, null, false); }
			这个Looper一般传入主线程的Looper。
 
	其他的都是上面的混合了。
 
 
 
  常用的Handler方法:
 
 
 
           handler.sendMessage(Message message);   //发送一个Message对象发送给消息队列。
           handler.post(myRunnable);      //发送一个包装Runnable的Message给消息队列。
           handler.postDelayed(Runnable r, Long time);  //定时不断发送一个包装Runnable的Message对象给消息队列。
 
	  Message方法就不说了上面有。
 
  我们在使用中需要调用的方法:
		通过上面分析我们知道除了主线程外其他线程都没有Looper(包含消息队列)也就不能通过Handler发送消息,
		所以在new Thread()的Run方法里面我们通过:
 
        Looper.prepare();  
                  即可生成一个Looper并且将新的消息队列绑定到当前线程,  看源码:
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { //如果当前线程已有Looper则报错。 throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); //与当前线程绑定 }
	       然后看一下Looper都有什么:
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); //新建了一个MessageQueue对象 mThread = Thread.currentThread(); //当前的线程。 } 
                      之后我们调用:	
 
Looper.loop();  //让这个消息队列运行,就是不断检测是否有新消息进来。 看里面源码:
                for (;;) {
                    Message msg = queue.next();     //从消息队列拿到消息
                    if (msg == null) {     
                      return;
                          }
                try {
              msg.target.dispatchMessage(msg);     //我们上面说到的msg.target就是发送这个Message的Handler本身。
              end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
                       }        循环检测队列是否为空   不为空就调用
 
        dispatchMessage(msg)  看看它的源码:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); //这里就其实就调用的Runnable的Run方法 } else { if (mCallback != null) { // 这个mCallback就是构造Handler是传入的Callback对象。 if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } 
 
               	结论一:
                  上述用if_else结构也是合理的,因为含有callback对象的message肯定不会再回调handlermessage 
		  因为我们只有传入一个Runnable对象它会在内部新建一个Message ,而这与sendmessage方法发送的Message
		  完全是两个不同的对象,我们的sendmessage方法只对应上述的handleMessage(msg);
		结论二:
		  如果传入了Runnable对象那么Callback对象的方法以及handlermessage()方法便不会执行, 再次强调Callback是Handler构造时传入的。
                结论三:
		  如果Callback中的返回值为false,则会继续执行handlermessage(),否则不会执行。
 
     	 ok到这里核心部分完成了 还有一些零散的东西:
 
   Looper.getMainLooper();     得到主线程的Looper对象,在构造Handler时如果传入这个则与主线程的消息队列绑定, 一般在主线程里用无参构造Handler
				自然与主线程的消息队列绑定,  这个可用于子线程绑定主线程新Looper。
 
 
Looper.prepareMainLooper(); 同上这个我们不用管 Activity生命明周期自己调用,Activity生命周期便是在主线程里执行的。
 
 
 

形象一点说MessageQueue就像一个物品输送台, Message则是物品, Handler则是将物品放置输送台上的机器,

		所以多个Handler与一个MessageQueue绑定, 一个Handler不能与多个MessageQueue绑定,因为物品只能放置一个地方,
		至于一个仓库(线程)为什么只能有一个MessageQueue (可能是因为钱不够吧
正在上传…
取消
!) 估计是代码设计考虑的。		
 
  				                                                                                         不才,如有不正请指导。。
 
 
 
 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值