编程进阶网编程进阶网
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 1.1App启动流程梳理
  • 1.2ActivityThread分析
  • 1.3Context设计思想
  • 2.1Activity基础介绍
  • 2.2Activity启动流程
  • 2.3Activity布局创建
  • 2.4Activity布局绘制
  • 2.5Service基础介绍
  • 2.6Service启动流程
  • 2.7Receiver广播基础
  • 2.8Receiver深入原理
  • 2.9ContentProvider分析
  • 2.10Fragment实践
  • 2.11Intent深入思考
  • 3.1Paint和Canvas
  • 3.2View的绘制基础
  • 3.3onMeasure流程设计
  • 3.4onLayout流程设计
  • 3.5onDraw流程设计
  • 3.6View工作原理
  • 3.7View刷新设计流程
  • 3.8自定义View控件
  • 3.9自定义ViewGroup控件
  • 4.1Handler基础使用
  • 4.2消息机制流程分析
  • 4.3Handler深度解析
  • 4.4Message深度理解
  • 4.5MessageQueue解析
  • 4.6Looper深度解析
  • 4.7理解Handler同步屏障
  • 4.8ThreadLocal分析
  • 4.9ThreadLocal场景
  • 5.1View事件设计思考
  • 5.2View滑动冲突处理
  • 5.3View事件源码分析
  • 5.4View事件总结案例
  • 6.1DecorView设计思想
  • 6.2视图的载体View
  • 6.3视图管理者Window
  • 6.4窗口管理服务WMS
  • 6.5布局解析者Inflater
  • 7.1AsyncTask深入介绍
  • 7.2HandlerThread设计
  • 7.3IntentService设计
  • 8.1IPC通信方式介绍
  • 8.2AIDL进程间通信
  • 8.7Binder通信机制设计
  • /zh/android/basic/9.1注解设计思想和原理.html
  • 9.2APT技术设计详解
  • 9.3APT多种案例实践

Android基础入门

目录

  • 1.1App启动流程梳理
  • 1.2ActivityThread分析
  • 1.3Context设计思想
  • 2.10Fragment实践
  • 2.11Intent深入思考
  • 2.1Activity基础介绍
  • 2.2Activity启动流程
  • 2.3Activity布局创建
  • 2.4Activity布局绘制
  • 2.5Service基础介绍
  • 2.6Service启动流程
  • 2.7Receiver广播基础
  • 2.8Receiver深入原理
  • 2.9ContentProvider分析
  • 3.1Paint和Canvas
  • 3.2View的绘制基础
  • 3.3onMeasure流程设计
  • 3.4onLayout流程设计
  • 3.5onDraw流程设计
  • 3.6View工作原理
  • 3.7View刷新设计流程
  • 3.8自定义View控件
  • 3.9自定义ViewGroup控件
  • 4.1Handler基础使用
  • 4.2消息机制流程分析
  • 4.3Handler深度解析
  • 4.4Message深度理解
  • 4.5MessageQueue解析
  • 4.6Looper深度解析
  • 4.7理解Handler同步屏障
  • 4.8ThreadLocal分析
  • 4.9ThreadLocal场景
  • 4.9深入理解消息机制
  • 5.1View事件设计思考
  • 5.2View滑动冲突处理
  • 5.3View事件源码分析
  • 5.4View事件总结案例
  • 6.1DecorView设计思想
  • 6.2视图的载体View
  • 6.3视图管理者Window
  • 6.4窗口管理服务WMS
  • 6.5布局解析者Inflater
  • 7.1AsyncTask深入介绍
  • 7.2HandlerThread设计
  • 7.3IntentService设计
  • 8.1IPC通信方式介绍
  • 8.2AIDL进程间通信
  • 8.7Binder通信机制设计
  • 9.1注解设计思想和原理
  • 9.2APT技术设计详解
  • 9.3APT多种案例实践

4.1Handler基础使用

01.Handler必备知识点

  1. 消息机制背景:子线程和主线程无法直接通信(举个例子,子线程做耗时操作完后需要更新主线程UI),这个时候就有了消息机制,主要是为了实现跨线程通信!
  2. 消息机制四要素:Message消息,Handler处理者(发消息和回调消息),MessageQueue消息队列(存储消息体),Looper(轮询,获取消息和处理消息)

03.子线程中定义Handler

子线程创建Handler会出现什么问题?一个线程中Looper可以是多个吗?

  1. 崩溃,handler运行是依赖Looper的,而Looper一个线程只允许有一个(应用初始化时ActivityThread会在主线程初始化Looper),其他线程不允许访问。
  2. 一个线程中,Handler可以是多个,Looper必须只有一个。handler其实间接跟线程绑定到一起,Handler所创建的线程中有Looper对象并且启动循环(其实是Looper)。

避免子线程手动创建looper。如果刻意在子线程中创建Looper,当消息处理完后,这个子线程的Looper则会一直处理等待的状态,建议不需要的时候终止Looper。

06.不建议在子线程访问UI

UI控件不是线程安全,多线程并发可能导致UI更新处于不可控,为何系统不设计成对UI控件访问加锁机制呢?

  1. 加锁让UI访问和更新变得复杂。
  2. 锁机制,在UI高频率刷新过程中,会降低效率,因为锁机制会阻塞线程执行。

07.子线程更新UI方式

  1. 主线程中定义Handler,子线程通过mHandler发送消息,主线程Handler的handleMessage更新UI
  2. 用Activity对象的runOnUiThread方法
  3. 创建Handler,传入getMainLooper,使用handler.post更新UI
  4. View.post(Runnable r)

08.解决Handler内存泄漏

  1. Handler内存泄漏原因:核心原因是生命周期长短造成,主要是Handler创建会隐式持有一个Activity,当Activity销毁后消息队列中仍然有未处理完的消息,Message会持有handler引用,Handler又持有Activity的引用,导致Activity的内存资源无法及时回收,引发内存泄漏。
  2. Handler内存泄漏解决方案:1.Activity销毁时移除所有消息;2.使用弱引用关联Handler。

4.2消息机制流程分析

01.消息机制核心思想

02.Handler发送消息

  1. 构造Handler对象,如果不传Looper对象,则会取当前线程关联的Looper【跟线程关联用到了ThreadLocal】。在主线程,系统在启动时,ActivityThread中main方法会给我们构建一个UI线程的Looper。
  2. 使用Handler发送消息,不管用那种方式,最终都会调用到sendMessageAtTime,发送消息肯定要有个容器来装消息,这里就用到了消息队列!

03.MessageQueue存储消息

  1. MessageQueue消息队列什么时候创建的?在创建Looper的时候,就创建了MessageQueue对象,这说明一个Looper对应一个MessageQueue消息队列。
  2. 消息队列如何存储消息?将消息Message对象存储到消息队列中,注意:发送延迟N毫秒的消息,消息队列会根据消息自带的时间排序来保证消息的先后顺序。

04.Looper循环分发消息

  1. Looper创建时机。在ActivityThread中的main方法中创建,然后用ThreadLocal将线程和Looper进行绑定。一个线程只能有一个Looper!
  2. Looper轮询器工作原理:

消息机制总结分享

  1. 一、在创建 Handler 实例时要么为构造函数提供一个 Looper 实例,要么默认使用当前线程关联的 Looper 对象,如果当前线程没有关联的 Looper 对象,则会导致抛出异常
  2. 二、Looper 与 Thread ,Looper 与 MessageQueue 都是一一对应的关系,在关联后无法更改,但 Handler 与 Looper 可以是多对一的关系
  3. 三、Handler 能用于更新 UI 有个前提条件:Handler 与主线程关联在了一起。在主线程中初始化的 Handler 会默认与主线程绑定在一起,所以此后在处理 Message 时,handleMessage(Message msg) 方法的所在线程就是主线程,因此 Handler 能用于更新 UI
  4. 四、可以创建关联到另一个线程 Looper 的 Handler,只要本线程能够拿到另外一个线程的 Looper 实例

4.3Handler深度解析

Handler深度解析和思考如下所示:

  1. 创建时机:在创建Handler对象时,在构造方法中会获取当前线程的Looper和MessageQueue,当然还会对消息callback赋值,设置消息是否是同步消息等等参数。
  2. 发送消息:不管那种方式发消息,最后都会调用sendMessageAtTime(),将消息体Message放到消息队列中【消息体中有指向handler引用,还有时间,what等】。
  3. 发送延迟消息:直接放到消息队列中,然后按照触发时间进行排序,保证队头的时间最小、队尾的时间最大。
  4. 处理消息:looper从消息队列里拿到消息后,然后交给handler去处理,最后会回调分发到dispatchMessage方法中。

什么是同步消息?什么是异步消息?分别应用到什么场景?

  1. 举一个例子。开发人员在100毫秒发送100个handler消息,Activity在不同生命周期加载View也会涉及到handler消息处理,那么如何设计可以让系统UI消息优先处理,优先做系统UI刷新?
  2. 发送消息太多会出现什么问题?1.会导致Looper负载高,任务挤压导致阻塞,导致业务出现bug;2.消息队列有一些消息处理非常耗时,导致后面的消息延时处理;
  3. 如何解决发送大量高频消息?可以使用独享Looper的handler,这样就跟主线程UI的Looper处理消息起到了隔离,不会影响主线程!

4.4Message深度理解

先来了解下Message,如果是你,你会如何设计消息体。那么考虑点有那些?

  1. 消息体需要能附带传递的内容【可以设计属性object】,发送消息和接受消息处理需要通过code来判断【可以设计属性what】,延迟消息需要附带时间【可以设计属性when】
  2. 使用handler发送,在处理消息的时候需要知道是那个handler发送的【可以设计属性target】,通过回调处理消息【可以设计属性runnable】
  3. 当开发者使用handler发送大量消息,系统可以优先处理系统UI级别消息,需要区分同步还是异步消息【可以设计属性flags】

消息使用频率高,而且有时候会很多,比如1000个消息,我肯定希望消息体创建能否做到复用【避免高频创建和销毁】?

  1. 那么如何做,这种场景明显就是,如果存在,则重用该对象,而不是创建一个新的对象。如果不存在,则创建一个新的对象并将其添加到共享池中,以供以后使用。利用享元模式!
  2. 消息的创建:可以看到源码中使用到了对象池,能否做到message复用。

4.5MessageQueue解析

  1. MessageQueue结构是如何设计:主要包含插入数据和取出数据,可以使用链表。
  2. MessageQueue是何时创建,可以创建多个吗:
  3. MessageQueue插入消息原理是:
  4. 如何处理延时消息,延时消息会打乱链表顺序吗:
  5. MessageQueue取出消息原理是:

4.6Looper深度解析

贡献者: yangchong211