Toast 源码实现 (完结)

    1. 从构造函数来看, 构造函数做的事情有: 

--> 指定 Toast 对应的 context 环境
--> 创建 TN 提供给 ToastManagerService 的 binder 接口.
--> 获取到 系统指定的在 Y 位置 上的 偏移像素.
Toast 源码实现 (完结)_第1张图片

    2. 针对 Toast的使用, Toast 类提供了一个 工具构造方法 Toast.makeText():  ------ > 从 这个 地方我们 可以知道 通过  调用 setView() 来完成对 mNextView 进行赋值,  来达到 自定义 layout 的目的.

--> 创建 Toast 对象.
--> 获取LayoutInflater, 然后 渲染 出 layout 文件 transient_notification 文件 对应的 View 树形图. 并对其中  R.id.message 对应的 TextView 进行赋值.
--> 将 inflate 获取到的 View 设置到 result 的 mNextView 这个属性上.
--> 设置 Toast 对应的 View 的展示时间. 有 LENGTH_LONG(3.5s) 和 LENGTH_SHORT(2s)

Toast 源码实现 (完结)_第2张图片

    3. 使用 Toast.makeText() 只是 获取到 一个 Toast 对象, 那么我们怎么展示它呢? 这就用到了 Toast 的 show() 方法了.


--> 获取 INotificationManager 对应的 service 的引用.
--> Toast 中的 mNextView 赋值给 TN 对象的 mNextView 这个属性上.
--> 调用   INotificationManager 对应的 service 把 tn 放到 对应的 Toast 队列中. 


Toast 源码实现 (完结)_第3张图片


    4. enqueueToast 的实现逻辑为:


根据传入的 pkg 判断是否是系统Toast, 然后 在 mToastQueue 上加同步锁, 然后 根据 pkg 和 callback (即 TN 对象的引用 来查询是否已添加过这个Toast).

Toast 源码实现 (完结)_第4张图片

当 mToastQueue 中 没有 这个 Toast 对应的 ToastRecord 的时候, 则重新创建一个 ToastRecord 添加到 mToastQueue 这个队列中, 当 判断队列中只有 一个 ToastRecord 时,则 调用 showNextToastLocked() 方法用来展示 Toast.

Toast 源码实现 (完结)_第5张图片



    5 在 showNextToastLocked() 中 会先从 mToastQueue 中 取出 ToastRecord, 然后 调用 ToastRecord 对应的 callback (即 TN ) 中的 show() 方法显示视图.


    
Toast 源码实现 (完结)_第6张图片


第一部分:  分析 show() 方法.


其中 TN.show() 的实现为:

    
Toast 源码实现 (完结)_第7张图片

其中 mShow 对应的 Runnable 中的 run() 方法实现为:
     
Toast 源码实现 (完结)_第8张图片



在 handleShow() 中 会把 mNextView 设置 给 WMS 用于 展示.

Toast 源码实现 (完结)_第9张图片



第二部分: 分析超时


在 showNextToastLocked() 还会设置 一个超时监听.

当 Toast 的显示时机 到 long_delay 或 short_delay的时候 回调  MESSAGE_TIMEOUT 对应的 msg 事件.
Toast 源码实现 (完结)_第10张图片


则 handleMessage() 的实现为: 会尝试 调用 handleTimeout 对应的方法, 并把 ToastRecord 作为参数传入.

Toast 源码实现 (完结)_第11张图片


如果 能在 mToastQueue 中查询到 对应的 Toast 则 调用取消逻辑:
Toast 源码实现 (完结)_第12张图片


在 cancelToastLocked() 方法中, 会先 调用 TN 中的 hide() 方法, 然后 将 ToastRecord 从 mToastQueue中 移除,  然后判断 mToastQueue中是否还有 其他的ToastRecord ,如果有 则 调用 showNextToastLocked() 进行处理.
Toast 源码实现 (完结)_第13张图片


其中 TN.hide() 做的事情 很简单,就是 把 View 从 WMS 中删除:
Toast 源码实现 (完结)_第14张图片

你可能感兴趣的:(Toast 源码实现 (完结))