设为首页 加入收藏

TOP

Handler,Looper,MessageQueue流程梳理(一)
2019-09-01 23:26:00 】 浏览:75
Tags:Handler Looper MessageQueue 流程 梳理

 

目的:handle的出现主要是为了解决线程间通讯。

  举个例子,android是不允许在主线程中访问网络,因为这样会阻塞主线程,影响性能,所以访问网络都是放在子线程中执行,对于网络返回的结果则需要显示在主线程中,handler就是连接主线程和子线程的桥梁。

 

1.handler基本使用方法

  看一下使用方法:

 public static final int EMPTY_MSG = 0;
    @SuppressLint("HandlerLeak")
    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 0:
                    Toast.makeText(MainActivitys.this, "接受到消息", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {
            @Override
            public void run() {
                handler.sendEmptyMessage(0);
            }
        }).start();
    }

  通过上边代码就完成了子线程向主线程发送消息的功能。

 

2. handler,Looper,MessageQueue 解释

  handler:负责发送和处理消息

  Looper:消息循环器,也可以理解为消息泵,主动地获取消息,并交给handler来处理

  MessageQueue:消息队列,用来存储消息

 

3.源码分析

  程序的启动是在ActivityThread的main方法中

public static void main(){
   Looper.prepare(); //1
   Handler handler = new Handler();//2
   Looper.loop();      //3
}

  Looper.prepare()会初始化当前线程的looper

 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));
    }

  会调用到sThreadLocal.set()方法,ThreadLocal是线程安全的,不同的线程获取到的值是不一样的,下面先分析一下ThreadLocal是如何做到线程安全。

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

  不同的线程会设置不同的looper,下面看一下ThreadLocalMap是如何存储数据的

  

 ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
      table = new Entry[INITIAL_CAPACITY];
      int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
      table[i] = new Entry(firstKey, firstValue);    
}

  ThreadLocalMap会创建一个数组,key是通过特殊的算法来创建出来,一个线程中会有一个ThreadLocalMap,这个map中会存多个ThreadLocal和values。

  下面看下ThreadLocalMap是如何set一个值的

  

private void set(ThreadLocal key, Object value) {

            // We don't use a fast path as with get() because it is at
            // least as common to use set() to create new entries as
            // it is to replace existing ones, in which case, a fast
            // path would fail more often than not.

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

 

  其实是遍历threadLocalMap中的table,如果当前table中存在threadLocal这个key就更新,不存在就新建。ThreadLocal的set方法到此结束。

 

  下面看下Handler handler = new Handler()中执行了哪些操作:

  public Handler(Callback callback, boolean async) {
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
      
    }

  重要的就是构造函数中这两个方法,在handler中初始化looper和messageQueue。这个就不展开讲了。

  

 

  下面看一下Looper.loop()这个步骤,我做了一些精简,把无关的代码去掉了。

   public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the mes
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Android GZIP压缩与解压 下一篇Android com.daimajia.slider.lib..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目