handler消息机制源码解析

1, 基本概念

Handler主要做什么?机制是怎样的?有其他相同或者类似的机制吗?

我们知道,Binder主要用于跨进程通信,Handler呢?主要用于进程内部进行通信,或者说进程内部不同线程之间进行通信,即是不同线程之间互相发送消息。

 

额外知识:

libcore/libart/src/main/java/java/lang/Thread.java

libcore/luni/src/main/java/java/lang/ThreadLocal.java

Thread类的内容有一个成员专门用于存储线程的ThreadLocal的数据。

ThreadLocal是做啥的呢?  啥都不说,直接上例子:

 

1.   private ThreadLocalmBooleanThreadLocal = newThreadLocal(Boolean);

2.    

3.   mBooleanThreadLocal.set(true);

4.   Log.d(TAG, [Thread#main]mBooleanThreadLocal=+ mBooleanThreadLocal.get());

5.    

6.   new Thread(Thread#1) {

7.   @Override

8.   publicvoid run() {

9.         mBooleanThreadLocal.set(false);

10.        Log.d(TAG,[Thread#1]mBooleanThreadLocal= + mBooleanThreadLocal.get());

11.  };

12.  }.start();

13.   

14.  new Thread(Thread#2) {

15.  @Override

16.  publicvoid run() {

17.        Log.d(TAG,[Thread#2]mBooleanThreadLocal= + mBooleanThreadLocal.get());

18.  };

19.  }.start();

20.   

输出结果:

21.  D/TestActivity(8676):[Thread#main]mBooleanThreadLocal=true

22.  D/TestActivity(8676):[Thread#1]mBooleanThreadLocal=false

23.  D/TestActivity(8676):[Thread#2]mBooleanThreadLocal=null

很神奇吧,可以这样理解, ThreadLocal虽然作为主线程的全部变量,但是在不同的字线程中都有各自一个独立的副本,彼此之间互不干扰。也就是说ThreadLocal是基于线程的。

那么Handler相关消息概念中为啥要使用ThreadLocal呢?

对于Handler来说,它需要获取当前线程的Looper,通过ThreadLocal就可以轻松实现Looper在线程中的存取.如果不采用ThreadLocal,那么系统就必须提供一个全局的哈希表供Handler查找指定线程的Looper,这样一来就必须提供一个类似于LooperManager的类了,这就是ThreadLocal的好处。

所以, 当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候,就可以考虑采用ThreadLocal。比如比如Looper、ActivityThread以及AMS等都用到了ThreadLocal。

 

 

主要做两件事情,1,(延时)发送消息;2,(延时)运行一个线程,最后都是以消息的形式封装处理。

主要包括三个类:handler, Looper, MessageQueue,还有Message

消息的表示:Message

消息队列:MessageQueue

消息循环,用于循环取出消息进行处理:Looper

消息处理,消息循环从消息队列中取出消息后要对消息进行处理:Handler

一个进程仅有一个looper,looper中包含一个消息链表(按照时间排序).

同一个handler可以对应(处理)不同的消息(Message)

2, 流程图

在apk启动时,会创建一个主线程,在ActivityThread的main函数中

【frameworks/base/core/java/android/app/ActivityThread.java

1.   public static void main(String[] args) {

2.   ···

3.   Looper.prepareMainLooper();

4.   ···

5.   Looper.loop();

6.   }

流程如下:


2.1 Looper初始化

7.   private static void prepare(booleanquitAllowed) {

8.           ···

9.           sThreadLocal.set(newLooper(quitAllowed));

10.  // 构造当前线程的Looper并且保存在sThreadLocal中

11.  }

 

12.  private Looper(boolean quitAllowed) {

13.          mQueue = new MessageQueue(quitAllowed);//构造消息队列 MessageQueue

14.          mThread = Thread.currentThread();

15.      }

 

 

16.  MessageQueue(boolean quitAllowed) {

17.          mQuitAllowed = quitAllowed;

18.          mPtr = nativeInit();// 该函数是一个C/C++层函数

19.      }

可以看看mQuitAllowed的定义:

20.  // True if the message queue can be quit.

21.      private final boolean mQuitAllowed;

该变量为false时表示不可以退出,只有主线程在调用prepare函数时传入false。也就是说仅有主线程不允许退出。

2.2 获取当前线程的Looper

直接看myLooper函数:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值