您的位置:首页 > 移动开发 > Android开发

深入Android Handler源码,分析主线程、子线程通讯原理

2017-01-12 16:54 483 查看
Android工作已经用不少的时间了,后悔当初没有写博客。最近一段时间才开始写博客的,其实我感觉并不是技术很厉害的人,才可以写博客。我写博客的原因,主要就是督促自己学习,不断的提升的自己。

好吧!废话不多说,开始今天的主题吧!Handler,大家可能看到Handler之后都感觉,这个我会用,不就Android里面经常用来更新UI的么,对,这么说也不是不对。但是这么说的肯定是没有对Handler或者AsyncTask有过深入研究的,首先Handler并不是用来更新UI的,它的作用是子线程与主线程通讯,更新UI只是随便。

好的下面我们开始先分析下Handler的源码!我们在使用Handler的时候主要是使用的sendMessage方法,那么我们进到sendMessage方法里面看看,它是这样的↓一般走到这一步之后就看不到源码了。(因为API版本不同,可能看到也不同所以没有关系,明白流程就好)



最后会进入到这样一个方法里面↓(高版本的API已经进行了进一步的封装,这是在低版本找到的)

public boolean sendMessageAtTime(Message msg, long uptimeMillis)

    {

        boolean sent = false;

        MessageQueue queue = mQueue;

        if (queue != null) {

            msg.target = this;

            sent = queue.enqueueMessage(msg, uptimeMillis);

        }

        else {

            RuntimeException e = new RuntimeException(

                this + " sendMessageAtTime() called with no mQueue");

            Log.w("Looper", e.getMessage(), e);

        }

        return sent;

    }

看到这里大家可能就会看明白许多了,这个方法就是把消息压入到了消息队列当中了,等待Looper进行抽取处理。那它是怎么拿到消息的呢?刚才就说了是Looper进行轮询抽取,那么到Looper类中可以看到一个loop方法,看重点,它是调用了消息队列的.next方法,将消息在队列中抽取出来,也就是说enqueue入队,next出队。

那么我就该说说Looper了,它是怎么用的。想用Looper必须要调用它的prepare()方法,那么这个方法是干什么的呢?看代码!

private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}


通过代码一看就看出来最后new
了一个Looper。对他就是用来实例化Looper对象的,但是你可能会看到一个叫sThreadLocal的变量,那么它是用来干什么的呢?我就直接跟大家说了吧!它是在java的并发包中的,主要是用来数据隔离的,比如线程中需要一个变量,但是线程的数量又不确定,也就是说每个线程中的这个变量都不一定是什么,但是又怎么能准确的拿到呢?就用到了这个ThreadLocal,它的主要功能就是防止数据脏读,用来进行数据隔离的。调用set就是将数据放进去。Loope又通过myLooper将Looper对象取出。也就是说,那一个线程调用prepareI()方法,这个线程就会关联一个Looper对象,那这个Looper.prepare是什么时候调用呢?为什么我们用Handler的时候为什么没有调用呢?

大家到Activity中可以去看看,在main方法中,系统就已经帮我们调用了,(在main方法中调用了Looper.prepareMainLooper),所以我们可以直接使用Handler。

大家是不是感觉这篇博客全是文字很无聊啊?其实我也感觉到了!我已经是捞干的了,大家见谅啊!

那么我们总结下:Hanlder的机制是不是这样的?子线程调用sendMessage方法将消息压入消息队列之后,主线程开了一个Looper轮询器,不断的轮询从这个Handler发送过来的消息,轮询到了之后调用handlerMessage方法进行处理。过多的细节我就不给大家阐述了,在下献上一副图供大家参考↓


好了,多了我就不说了!我用java代码简单的实现了一下Hanlder,有兴趣的朋友们可以下载下来看看,有不同意见的可以留言吐槽。
a1b7
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 源码 通讯