从顶层设计的角度对Android ANR机制的一些思考

“不能在子线程中更新UI”
“主线程不能做耗时操作”

这些话被我们奉为圭臬,但有多少人想过为什么不能在子线程中更新UI?为什么主线程不能做耗时操作?

首先先要从Android中的一个叫ANR的机制一点一点说起!

在说ANR之前 我们还是先要了解一下什么是ANR

ANR全名:Application Not Responding 即“应用程序无响应”。首先我们尝试去Android Developers官网寻找一下对于ANR的权威解释


Android开发者官网截图

这是Android开发者官网开发者指南中对ANR以及触发机制的描述, 文档第一段可以看到这句话:

"系统会通过显示一个说明您的应用已停止的响应的对话框来防范一段时间内的响应不足的应用程序”。

读起来虽然很晦涩...但我们还是会有一个疑问:文中所说的防范 具体是防范哪些应用程序? 该应用程序又是执行在哪个线程?。不急,我们尝试从第二段文档中找下答案,注意这句话:

“在您的应用程序执行可能冗长的操作的任何情况下, 您不应该在UI线程上执行工作”。

其中您不应该在UI线程上执行工作这句话还被黑体加粗。

由此,结合文档我们大致明白,之前提到的“防范的应用程序”指的是耗时操作,“执行的线程“是UI线程。再结合第二段文档中的话可以得出一个结论:当你在UI线程当中执行耗时操作的时候,会触发Android防范机制:ANR

那么今天我们讨论的重点并不在于此,今天我们要从设计师纬度去分析:

为什么要有ANR机制以及ANR机制在Android程序中存在的必要性

那好,我们根据开发经验 大胆想象一下是否可以把App的代码宏观上分为两种类型:
一种是 UI操作(即时反馈)
UI操作(包括但不限于):

  • 界面的渲染
  • View的绑定,刷新
  • 动画

一种是 业务逻辑(耗时操作)
业务逻辑相关(包括但不限于):

  • 网络数据的收发和上传
  • 数据库的CRUD操作
  • IO的读写


    图片

    如图,现在我们做一个假设:假设我们的这些代码共用一个线程,会发生什么问题呢?

首先 默认情况下代码执行规则是从左至右,从上至下同步执行,那么如果有耗时操作,代码就会阻塞。反馈到界面上最直观的感受就是响应延迟卡顿,如果你代码书写顺序颠倒 控件拿不到数据,还会报出空指针等等的异常。用户体验不能用糟糕形容,简直就是毫无用户体验。

显然 谷歌工程师不会如此愚蠢。工程师们为了规避这个问题,这就要引入Android中一个重要概念叫做:异步

异步是目的,想实现这个目的就需要用到多线程,那么多线程状态下Android的代码又是如何去执行?

首先我们要知道多线程执行的本质是:CPU在多条线程之间做快速的切换,它是随机并发执行

我们的代码要想在这种环境下异步执行会面临以下问题:

  • UI操作的同步问题
  • UI操作(View)的不可预期性

解释一下这些问题,我们知道UI操作是即时反馈


模拟线程执行任务

如图 我们假设有三条线程,线程一给控件赋值,线程一的控件值依赖于线程二网络请求拿到的数据,线程二的控件赋值又依赖于线程三中数据库查询到的值,请问我如何确保多线程并发访问时一定先执行线程三 再执行线程二 最后执行线程一呢?换句话说我如何解决同步问题?

Ok 肯定有小伙伴说 想那么复杂干嘛,加个锁不就完事儿了嘛...加锁是能保证线程安全,互斥,这当然没问题, 重点是,你如何确定加锁的位置?如果盲目加锁还可能会让控件(View)处于一个不可预期的状态,一不小心还可能造成多线程死锁的现象。

既然无法用代码的方式去解决这个问题,那我们就做减法,从书写方式上寻找突破点 既然不能加锁也不能让线程同步,那我们就索性把UI操作单拎出来,你们玩你们的,事成之后告诉我一个结果就行,控件不就是想要这么一个结果渲染界面嘛。

按着这个思路,其实这个问题很好解决 我们只需要在编写代码的时候遵循一个规则就可以完全规避Android中UI操作在多线程异步之间的冲突。

这个规则就是:只要是涉及到UI操作的代码,我们都单独的放到一个线程中,这个存放UI的线程要想满足UI控件的正常工作必须要满足:线程非安全,不能加锁,不能阻塞

到此 这个存放UI的线程想必大家都知道了,对!没错!就是我们口口相传大名鼎鼎的:"主线程"又称之为UI线程。

Android单线程模式

这也就回答了开头"为什么不能在子线程中更新UI?为什么主线程不能做耗时操作"的迷之疑问...但似乎有相当一部分开发者只是机械型的遵循这一规则。

谷歌为了最大化提升用户体验 让开发者都遵守这个规则,保证规则的良性循环 ,ANR机制就诞生了,Android在主线程之间会设置一个5s——20s不等的时间阀值(产生ANR的上下文不同,超时时间也会不同),如果主线程中的程序运行/阻塞的时间超出了这个阀值,就会抛出ANR异常,如下图


开发者官网截图

所以这也就是Android为什么会有ANR这么一个机制,ANR的必要性也由此显现。

掌握原理及其设计思想之后 写起代码来才能举一反三更加得心应手,不会再为某一个莫名其妙的bug头疼半天,但不得不说 谷歌工程师代码设计的还是非常之精妙的,其中的思路非常宝贵值得我们借鉴。

但以上仅是个人对ANR机制狭义上的理解(也算是自问自答式的圈地自嗨???哈哈),旨在集思广益交流分享,如有不同观点非常欢迎与鄙人探讨学习,如果此文章对你或多或少有些启发,那就点个爱心加关注吧~ 后续会尽可能的分享更多高质量的文章于大家交流学习。

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

推荐阅读更多精彩内容