系统Handler源码分析

参考 http://www.jianshu.com/p/ac50ba6ba3a2

          http://www.jianshu.com/p/aa6b6152217d

几个要点

消息其中包括:

     我们自己的操作消息(客户端的 Handler)

      系统的操作消息(系统 Handler):比如启动 Activity 等四大组件(例如       突然来电话的时候跳转到电话界面)

线程不安全问题归根结底主要涉及到变量的多线程访问问题,例如变量的临界问题、值错误、并发问题等

1 系统的handler类名为大写的H (继承Handler)

2 为ActivityThread 的成员变量,在 new ActivityThread 的时候,系统的 Handler 就初始

3 在 main 方法里面,然后创建了 Looper,然后开启消息循环。之所以我们的APP能够一直运行着,就是因为 Looper.loop() 里面是一个死循环:

public static void loop() {

   for(;;) {    }

}

4 在非主线程里面我们也可以搞一个 Handler,但是需要我们主动去为当前的子线程绑定一个 Looper,并且启动消息循环。

5 post方法(封装了带Runnable的Message) 最终都是调用sendMessageAtTime方法,把消息放到消息队列里面:

6 消息并不是一直在队列的尾部添加的,而是可以指定时间,如果是立马需要执行的消息,就会插到队列的头部,就会立马处理,如此类推。

7 ThreadLocal 是JDK提供的一个解决线程不安全的类,线程不安全问题归根结底主要涉及到变量的多线程访问问题,例如变量的临界问题、值错误、并发问题等。这里利用ThreadLocal 绑定了 Looper 以及线程,就可以避免其他线程去访问当前线程的 Looper 了。

8  Looper 与线程的关联是通过 ThreadLocal 来进行的

9  MessageQueue 是Looper对象的成员变量 (消息队列是通过链表实现 指向下一个结点)

Looper与当前线程绑定

调用prepare(prepareMainLooper())方法来关联线程和Looper  //sThreadLocal.set(newLooper(quitAllowed));


Looper的成员变量sThreadLocal

static final ThreadLocal sThreadLocal =newThreadLocal();

在prepare方法中new了一个Looper并且设置到sThreadLocal里面sThreadLocal.set(newLooper(quitAllowed));

消息池的概念

1 Message Pool消息池的概念——重复利用Message (利用享元模式去循环利用)

2 通过obtain方法取出一条消息的时候,如果发现当前的消息池不为空,那就直接重复利用Message(已经被创建过和handle过的);如果为空就重新 new 一个消息。这就是一种享元设计模式的概念

3 消息的去取出并不是直接就从队列的头部取出的,而是根据了消息的when时间参数有关的,因为我们可以发送延时消息、也可以发送一个指定时间点的消息

迭代消息过程

1 首先拿到Looper对象(me),如果当前的线程没有Looper,那么就会抛出异常,这就是为什么在子线程里面创建Handler如果不手动创建和启动Looper会报错的原因。

2 Looper的成员变量MessageQueue,在MessageQueue里面不断地去取消息

for(;;) { 

      Message msg = queue.next();// might block

if(msg ==null) {

// No message indicates that the message queue is quitting.

return;

        }

//处理消息

try{ 

 msg.target.dispatchMessage(msg); 

  }

finally{ }  

   } 

msg.recycleUnchecked();//回收消息}

Handler、Looper是怎么关联

在初始化Handler类中

public Handler(Callback callback, booleanasync){   

 mLooper = Looper.myLooper();//见下文备注 第二块核心代码

//如果当前线程(子线程)没有Looper,就需要我们程序要去手动prepare以及启动loop方法了

//子线程里面默认没有Looper循环器

if(mLooper ==null) {

thrownewRuntimeException("Can't create handler inside thread that has not called Looper.prepare()"); 

   }  

  mQueue = mLooper.mQueue; 

   mCallback = callback;  

  mAsynchronous =async;

}

第二块核心代码

public static @Nullable Looper myLooper(){

returns  ThreadLocal.get();//返回与当前线程绑定的Looper

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容