Handler,MessageQueue,Looper,Runnabler的关系

首先简单说一下进程与线程的区别。进程(Process) 是程序的一个运行实例,以区别于“程序”这一静态的概念而线程(Thread)则是cpu调度的基本单位。也可以这样想,进程是划分程序所得到的内存区域,而线程是对cup调度的划分。

我们第一印象中Handler,MessageQueue,Looper之间的关系在头脑或许是不相关的,怎么也联系不起来。但在使用中它们又感觉是一体的,这是怎么回事呢?

我们简单的说下他们是干嘛的:Handler相当于事情的处理者,怎么去处理消息由它决定。MessageQueue是一个线程所有消息存放的地方。而Looper它的任务就是推动这些消息执行,它是一个死循环,不断从MessgeQueue中取出消息交给对应的Handler处理。Handler是消息的发起者也是执行者,至于为什么大费周章的让它走这样的流程,是为了保证其“有序性”。

一个线程只有一个Looper,Looper只对应一个MessageQueue,而MessageQueue中可以有很对Message,但每个Message只对应一个Handler去处理。

关于Handler,我们平时可能是下面这样用的。
在主线程中:

private Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        switch(msg.what){
            //我们处理的事情
        }
    }

};

在子线程中:

Message message = Message.obtain();
message.what = HELLO_WORD;
handler.sendMessage(message);

或者

mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                //更新UI
                            }
                        });

这样我们在子线程中发的指令 ,就可以在主线程执行了 。在子线程里调用post(),传了一个Runable进去,并在run();方法中执行更新UI操作 。这种看似在子线程里更新UI又是怎么回事呢?我们带着这些疑问探究下源码吧。

我们看看使用Looper线程的普通线程和主线程的列子:
普通线程:

class myThread extends Thread{
    public Handler mHandler ;
    public void run(){
        //第一步
        Looper.prepare();
        //第二步
        mHandler = new Handler(){
            public void handleMessage(Message msg){
                switch(msg.what){
                    //我们处理的事情
                }
            }
        };
        //第三步
        Looper.loop;
    }
}

主线程:
frameworks\base\core\java\android\app\ActivityThread.java

public static void main(String[] args) {
        ... ...
        //第一步,和普通线程有点点区别,稍后我们再分析
        Looper.prepareMainLooper();
        //创建一个线程对象
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        //第二步 ,不是new的Handler而是thread.getHandler();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        ... ...
        //第三步一样
        Looper.loop();

可以看到两者的整体架构是一样的;

我们先看第一步:Looper.prepareMainLooper()。
frameworks\base\core\java\android\os\Looper.java

public static void prepareMainLooper() {
        prepare(false);//和普通线程一样先是调用了prepare;传入false代表线程不允许退出
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            //将其赋值给sMainLooper ,以表示主线程和其他线程不同;让其他进程都可以获取到主线程的looper对象(getMainLooper());
            sMainLooper = myLooper();
        }
    }

接下来我们看看 prepare()做了什么?

//这个可以理解为放Looper对象那个的容器
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //新建一个Looper对象,将其放入Looper容器中
        sThreadLocal.set(new Looper(quitAllowed));
    }

顺便看看Looper的构造函数

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

到现在为止我们还是没看到Looper和Handler之间的联系;

我们继续看第二步mHandler = new Handler();
看看Hand的构造函数:
frameworks\base\core\java\android\os\Handler.java

ublic 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对象中的MessageQueue;
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

这样就巧妙的将它们之间联系起来了。

我们来走一下消息处理过程,以便于更好理解:
handler.sendMessage(message);

public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

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 queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        //将消息放到MessageQueue;
        return enqueueMessage(queue, msg, uptimeMillis);
    }

我们来看看post()有什么不同

public final boolean post(Runnable r)
    {
    //就比sendMessage多一步 ,通过getPostMessage(r)将Runnable 封装为Message再将其放入MessageQueue中
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

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

现在我们已经将消息放进去了 ,那怎么执行起来呢?

就是第三步Looper.loop();
frameworks\base\core\java\android\os\Looper.java

    public static void loop() {

        //获取当前线程的Looper对象的实例
        final Looper me = myLooper();

        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        //取出其中的MessageQueue ;
        final MessageQueue queue = me.mQueue;
        ... ...

        for (;;) {
            //开始循环处理
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            ... ... 
            try {
                //交给了Message的target的dispatchMessage处理。
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            ... ...
            msg.recycleUnchecked();
        }
    }

由上我们可以得知,Looper循环处理MessageQueue中的message。最终将message给了message的target的dispatchMessage处理。
进一步探究target是何方神圣:
在Message中是个成员变量。
在前面发送消息的流程中我们走到了 enqueueMessage(queue, msg, uptimeMillis);
我们继续看看:
frameworks\base\core\java\android\os\Handler.java

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        //在这里把Handler对象自己赋值给了target ,是不是感觉绕了个圈又回来了
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        //将消息压如队列中的具体实现,有兴趣的可以自行阅读源码
        return queue.enqueueMessage(msg, uptimeMillis);
    }

好了现在我们知道了,通过message自己对应的Handler对象去处理。
最后我们看看Handler的dispatchMessage(msg);

public void dispatchMessage(Message msg) {
        //在msg.callback不为空的情况下优先通过msg.callback处理,也就是使用Post()时传入的Runnabler对象
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
            //在创建handler对象时如果传入了回调方法 ,则优先该回调方法
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            //最后有创建handler复写的handleMessage()进行处理
            handleMessage(msg);
        }
    }

private static void handleCallback(Message message) {
        //看这里明白了吧 ,看似开启了一个子线程。其实是在拥有该handler对象的线程进行出理的
        message.callback.run();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值