笔记:Handler

我一般创建Handler 是这样创建的

Handler handler = new Handler(new Handler.Callback() { 
   @Override    
    public boolean handleMessage(Message msg) {      
    Log.i("lpc", "----" + Thread.currentThread().getId() + "");    
    return false;    
}});
handler.sendEmptyMessage(0);

这样写法在主线程是没问题的

但如果在子线程中这样些就会报错

new Thread(new Runnable() {    
  @Override    
  public void run() {         
  Handler handler = new Handler(new Handler.Callback() { 
       @Override            
       boolean handleMessage(Message msg) {  
       Log.i("lpc", "----" + Thread.currentThread().getId() + ""); 
       return false;            
       }        
  });        
  handler.sendEmptyMessage(0);         
}}).start();

原因是源码中有这样一句

mLooper = Looper.myLooper();
if (mLooper == null) {    
    throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()");
}

也就是说mLooper为空导致的,需要在实例化Handler之前加上

Looper.prepare();

但是就很疑惑,在主线程中创建的Handler是在什么时候prepare的呢,最终原来是在ActivityThread中有这样一段代码

public static void main(String[] args) {
    ...
    Looper.prepareMainLooper();
    ...
    Looper.loop();
}

prepareMainLooper方法

public static void prepareMainLooper() {    
    prepare(false);    
    synchronized (Looper.class) {        
    if (sMainLooper != null) {            
        throw new IllegalStateException("The main Looper has already been prepared.");        
    }        
    sMainLooper = myLooper();   
}}

ok,加上prepare方法后但是收不到消息,怎么回事?原来还需加上

Looper.loop();

为什么呢,这就需要看下Looper.loop的代码了

public static void loop() {
    final Looper me = myLooper();
    ...
    final MessageQueue queue = me.mQueue;
    ...
    for (;;) {    
        Message msg = queue.next(); // might block   
        ....
        msg.target.dispatchMessage(msg);
   }
}

因为默认的是主线程的looper,即me对象,一直循环取的也是主线程中的MessageQueue对象,所以如果是子线程的情况,需要主动调用下loop方法才行。

在Handler中有send和post方法,这两个有什么区别呢

send方法和post方法实际上最终都会走到这个方法里面

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {   
   MessageQueue queue = mQueue;    
    if (queue == null) {        
    RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");
    Log.w("Looper", e.getMessage(), e);       
    return false;    
}   
   return enqueueMessage(queue, msg, uptimeMillis);
}

区别是在这里

public final boolean post(Runnable r){   
    return  sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {    
    Message m = Message.obtain();    
    m.callback = r;    
    return m;
}

实际上也是一个Message对象,只不过他的callback的值就是传入的Runnable,然后在Looper的loop方法中有这样一句代码

msg.target.dispatchMessage(msg);

所以最终会走到

public void dispatchMessage(Message msg) {    
    if (msg.callback != null) {        
        handleCallback(msg);    
    } else {
        if (mCallback != null) {            
              if (mCallback.handleMessage(msg)) {
                 return;           
               }        
        }        
        handleMessage(msg);    
    }
}

handleCallBack方法

private static void handleCallback(Message message) {  
     message.callback.run();
}

实际上只是执行了run方法,所以post方法能够实现UI的更新。但是注意,这并不是绝对的,run方法的执行是在创建此Handler的线程,而这不一定就是主线程。

你可能感兴趣的:(笔记:Handler)