Handler

什么是Handler机制?

handler是一种消息处理机制,用于线程之间通信。由于主线程不能做耗时操作,会导致ANR,子线程不能刷新ui,我们在做网络请求,或数据库操作等时,因为这些原因,所以我们就需要使用handler进行线程之间通信。

handler机制分为三部分: handler  looper  messagequeue

looper:消息轮询,不断在这里取消息,交给handler去处理

hander:发送消息,处理消息

messagequeue:消息队列,存储消息,遵循先进先出原则

我们创建出handler实例,通过sendmessage方法将消息发送出去,该方法调用了sendMessageDelayed(消息延时)的方法,此方法中做了一个延时判断,如果delayMillis<0,给他赋值为0表示立即发送,因为是延时发送,不可能出现负值。然后返回sendMessageAtTime方法,这个方法会帮我们拿到一个消息队列(mqueue,在looper的构造方法取出),通过enqueueMessage方法帮我们把拿到的queue,msg,以及uptimeMillis时间传递下去,在这个方法中又对msg.tager=this赋值,让它等于本类对象(handler),然后调用queue.enqueueMessage(msg, uptimeMillis)消息队列enqueueMessage方法,做判断对消息排序,谁优先谁执行,遵循先进先出原则。我们把消息发送出去,存放到messagequeue中,然后通过looper.loop()不断轮询取消息,通过msg.targer.dispatchMessage,也就是handler进行处理消息。而我们的looper在prepare方法中创建我们的looper实例,存放到ThreadLocal中(ThreadLocal相当于存放我们loop实例的一个容器,可以保证多个线程并发不相互干扰),同时做了一个判空处理,不为空就会抛一个异常,也保证了我们一个线程只有一个looper实例,在looper的构造方法中,创建了一个消息队列,同时创建了一个当前线程。looper.loop()方法,我们会拿到myloop的实列,通过实例拿到queue,消息队列通过.next方法把消息取出来,没有消息就结束,有消息交由msg.targer.dispatchMessage来处理(targer就是我们的handler),在处理的时候,我们会拿到系统当前开始的一个时间,进行处理,处理完给他结束时间。dispatchMessage()做了一个判断,msg.callback==null会走handleMessage,这是一个空方法,我们在创建handler时,会重写这个方法,所以我们的操作是在这里实现的(我们在handler的构造方法中可以看到我们的callback为null);如果我们做定时器时,使用postDelayed时它也是调用了sendMessageDelayed这个延时方法,它的参数getPostMessage当中把Runnable赋值给了我的callback,所以当它不为空时,会调用handleCallback方法,在run方法做我们的具体操作。

注意:在子线程创建handler,我们首先需要调用loop.parper()方法,创建完成后,调用looper.loop()方法,否则会报“没有loop.parper()方法”的异常,而在主线程创建handler时,系统已经帮我们创建好looper实列,在activitythread的main方法中,looper.prepareMainLooper()中知道prepareMainLooper可以拿到myLooper,而这个方法就是通过threadlocal拿到我们保存的looper对象。所以主线程可以不调用loop.parper()这个方法。

在使用handler出现的问题:内存泄漏

首先,handler很多时候也是作为一个内部类使用,改为静态内部类,因为静态内部类的实例对象不会和外部类的实例对象绑定。它只能访问外部类的静态成员变量或者静态方法,而静态的生命周期和application一样长,所以不会影响activity的回收。其次,handler经常执行一些耗时的操作,如果耗时任务还没有执行完成,而这个时候activity已经销毁,当gc回收的时候发现activity仍被持有,导致不能被回收,所以一般在activity销毁的时候(也就是onDestroy的时候)将所有消息清空(removeCallbacksAndMessages)并将handler置空。

内存泄漏的检测:在Androidstudio3.0以后,通过Android profiler(3.0以前使用Android monitor)中的memery选项,查看内存使用情况,如果检测某一个activity中是否存在内存泄漏,可以将该activity进行finish,然后手动触发GC,再对项目的包进行捕捉查看,如果gc后发现在对应包下,仍然存在改activity引用,说明该activity已经发生了泄漏,可以根据引用的对象,进行初步排查,当然不管使用studio自带的检测工具,还是使用MAT工具,只能检测出大部分的泄漏问题,或者有时候即使发现泄漏,很难确定位置,这个时候主要还是靠开发人员通过经验判断逐步排查。

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

推荐阅读更多精彩内容