Handler源码分析

一、Handler的创建

Handler的创建会关联一个Looper对象,而Looper对象关联着MessageQueen对象,所以在Handler创建时,取出LooperMessageQueen

public Handler(Callback callback, boolean async) {
    ...
    //取出Looper
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    //取出Looper中的MessageQueen
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

Looper是存放在ThreadLocal里面的,可以看下面的源码

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

整个创建的过程就完了,这里做了哪几件事:

  • 取出Looper
  • 取出Looper中的MessageQueen

二、Handler发送消息

1、方式一:sendMessage(Message msg)
public final boolean sendEmptyMessage(int what)
{
    return sendEmptyMessageDelayed(what, 0);
}

//往下追踪
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}

//往下追踪
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

//往下追踪
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
	//直接获取MessageQueue
    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);
}

//调用sendMessage方法其实最后是调用了enqueueMessage方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
	//为msg.target赋值为this,也就是把当前的handler作为msg的target属性
	//如果大家还记得Looper的loop()方法会取出每个msg然后执行msg.target.dispatchMessage(msg)去处理消息,其实就是派发给相应的Handler
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    //最终调用queue的enqueueMessage的方法,也就是说handler发出的消息,最终会保存到消息队列中去
    return queue.enqueueMessage(msg, uptimeMillis);
}
2、方式二:post(Ruunable r)
public final boolean post(Runnable r)
{
   return  sendMessageDelayed(getPostMessage(r), 0);
}

其实post()方法最终也会保存到消息队列中去,和上面不同的是它传进来的一个Runnable对象,执行了getPostMessage()方法,我们往下追踪

private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}

实质上就是将这个Runnable保存在Message的变量中,这就导致了我们下面处理消息的时候有两种不同方案

三、Handler处理消息

你还记得前面所说Loopermsg.target.dispatchMessage()方法吗?这个方法就是调用HandlerdispatchMessage()

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
	    //1. post()方法的处理方法
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        //2. sendMessage()方法的处理方法
        handleMessage(msg);
    }
}

//1. post()方法的最终处理方法
private static void handleCallback(Message message) {
    message.callback.run();
}

//2. sendMessage()方法的最终处理方法
public void handleMessage(Message msg) {
}

整个处理的过程就完了,这里做了哪几件事:

  • post()方法的处理方法就是将传进来的Runnable执行run()方法
  • sendMessage()方法的处理方法就是执行handleMessage()空方法,这也是我们为什么要在Handler重写这个方法的原因

三、Handler 的post(Runnable)和handleMesaage的用法

1).post(Runnable)用法:
package mountain_hua.learn_handler1;
 
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
 
public class MainActivity extends AppCompatActivity {
 
    //先在主线程中创建Handler,Handler会自动与主线程绑定
    private Handler handler=new Handler();
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        System.out.println("main thread id " + Thread.currentThread().getId());
        test_handmessage();
 
    }
 
    public void test_handmessage(){
        new Thread(){
            @Override
            public void run(){
                //处理信息
                try{
                    //模拟费时操作
                    System.out.println("run thread id " + Thread.currentThread().getId());
                    sleep(1000);
                    //这里使用Runnable
                    Runnable runnable=new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("Runnable thread id " + Thread.currentThread().getId());
                        }
                    };
                    //这里执行post(Runnable)操作
                    handler.post(runnable);
                }catch (Exception e){
                    e.printStackTrace();
                }
 
            }
        }.start();
    }
 
}

首先在主线程中创建了一个handler,这时handler会自动绑定主线程,然后在一个新线程里面创建了Runnable对象,并且用了handler的post(Runnable)操作来发送消息给在主线程中的handler执行。我们看看打印出来的结果:

07-30 21:34:23.891 21509-21509/mountain_hua.learn_handler1 I/System.out: main thread id 1
07-30 21:34:23.893 21509-21560/mountain_hua.learn_handler1 I/System.out: run thread id 9378
07-30 21:34:24.894 21509-21509/mountain_hua.learn_handler1 I/System.out: Runnable thread id 1

结果可以看到Runnable与main线程id相同,说明了Runnable里面执行的事件是被handler放在主线程中执行的,与Run所在线程无关 。

2).handleMessage用法:
package mountain_hua.learn_handler1;
 
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test_handmessage();
        test_handmessage1();
    }
 
    public void test_handmessage(){
        new Thread(){
            @Override
            public void run(){
                //处理信息
                try{
                    //模拟费时操作
                    System.out.println("run thread id " + Thread.currentThread().getId());
                    sleep(1000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                Message msg=new Message();
                // 也可以用下面两种方法获得Message
                // Message msg1=Message.obtain();
                // Message msg2=handler.obtainMessage();
                msg.what=0;//msg.what的类型是int型,作为msg的识别码
                msg.arg1=1;//msg.arg1的类型是int型,可以传递简单的参数
                msg.arg2=2;//msg.arg2的类型是int型,可以传递简单的参数
                msg.obj="Object类型";//msg.obj是Object型,可以传递任意参数
                //将Message发送给handler
                handler.sendMessage(msg);
 
            }
        }.start();
    }
 
    public void test_handmessage1(){
        new Thread(){
            @Override
            public void run(){
                //处理信息
                try{
                    //模拟费时操作
                    System.out.println("run thread id " + Thread.currentThread().getId());
                    sleep(2000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                Message msg=new Message();
                // 也可以用下面两种方法获得Message
                // Message msg1=Message.obtain();
                // Message msg2=handler.obtainMessage();
                msg.what=99;//msg.what的类型是int型,作为msg的识别码
                msg.arg1=100;//msg.arg1的类型是int型,可以传递简单的参数
                msg.arg2=101;//msg.arg2的类型是int型,可以传递简单的参数
                msg.obj="Object类型";//msg.obj是Object型,可以传递任意参数
                //将Message发送给handler
                handler.sendMessage(msg);
 
            }
        }.start();
    }
 
    Handler handler=new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    System.out.println("handleMessage thread id " + Thread.currentThread().getId());
                    System.out.println("msg.arg1:" + msg.arg1);
                    System.out.println("msg.arg2:" + msg.arg2);
                    break;
                case 99:
                    System.out.println("handleMessage thread id " + Thread.currentThread().getId());
                    System.out.println("msg.arg1:" + msg.arg1);
                    System.out.println("msg.arg2:" + msg.arg2);
            }
        }
    };
}

这里用两个Messge给主线程中的Handler发送消息,打印出的信息为:

07-30 21:19:08.532 2461-2782/mountain_hua.learn_handler1 I/System.out: run thread id 9311
07-30 21:19:08.532 2461-2783/mountain_hua.learn_handler1 I/System.out: run thread id 9312
07-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: handleMessage thread id 1
07-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg1:1
07-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg2:2
07-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: handleMessage thread id 1
07-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg1:100
07-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg2:101

可以看到handler处理消息队列是在主线程中处理的(handler在哪个线程中创建的就与哪个线程绑定), 与run存在的线程无关。

参考:

Android中Handler的post(Runnable)用法和handleMesaage用法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值