WMS的小问题

为什么WMS的启动使用Handler而不是新启动一个线程?

WMS(Window Manager Service)是Android系统中的一个重要服务,用于管理窗口的显示和布局。当需要创建一个新窗口时,WMS会根据窗口的属性和优先级决定其在屏幕上的位置,并为其分配一个合适的Z轴位置,以确保窗口的正确显示。

在处理窗口创建的过程中,WMS需要与UI线程进行交互,以便实时更新窗口的显示状态。因此,WMS使用了Handler的runWithScissors方法来在UI线程上执行一些必要的操作,例如更新窗口的属性和位置等。这种做法可以保证窗口创建过程不会阻塞UI线程,从而保证了系统的流畅性和稳定性。

相比于新开一个线程来处理窗口创建的过程,使用Handler的runWithScissors方法可以避免线程切换的开销和资源浪费,同时也可以确保对UI线程的访问是线程安全的,避免了可能出现的并发问题。因此,这种做法是比较合理和可行的。

为什么addWindow 的 状态定义在 WindowManagerGlobal 中?

addWindow 方法用于向 WindowManager 中添加一个新的窗口,这个方法涉及到了整个系统的窗口管理。WindowManagerGlobal 是一个全局的窗口管理器,它负责管理整个系统中的所有窗口,包括应用程序的窗口和系统的窗口。因此,将 addWindow 方法的状态定义在 WindowManagerGlobal 中是非常合理的,因为这样可以方便地管理和维护整个系统中所有窗口的状态。此外,由于 WindowManagerGlobal 是一个全局的窗口管理器,因此它可以在整个系统中被访问和使用,使得 addWindow 方法可以方便地被其他组件和应用程序调用。

一个小问题,为什么android 源码很少使用迭代器而使用for循环?

Android 源码大部分使用for循环而不是迭代器的原因主要有以下几点:

  1. 效率:for循环的效率比迭代器高,因为迭代器需要动态判断是否还有下一个元素,而for循环只需要在开始时获取集合的大小,然后按照索引遍历即可。

  2. 兼容性:迭代器是在Java 1.2引入的,而Android 的API 最低支持版本是1.6,为了兼容低版本的Java,Android 源码中大部分使用for循环。

  3. 代码简洁:for循环的语法比迭代器简洁,代码可读性更高。

  4. 集合类型:Android 源码中大部分使用的集合类型是数组和ArrayList,它们的元素个数是固定的,适合使用for循环遍历。

当然,在某些场景下,Android 源码中也会使用迭代器来遍历集合,比如遍历HashMap等动态集合。

为什么 WindowManagerGlobal 要通过ViewRootImpl去向WMS addWindow,而不能直接addWindow?

WindowManagerGlobal 之所以要通过 ViewRootImpl 去向 WindowManagerService (WMS) addWindow,是因为在 Android 系统中,所有的视图都是由 ViewRootImpl 来负责管理的。ViewRootImpl 负责与 WMS 进行通信,将视图树中的变化传递给 WMS。因此,只有通过 ViewRootImpl 才能将窗口添加到视图树中,最终交由 WMS 进行管理。直接调用 addWindow 方法是无法实现这个过程的。

WindowManagerGlobal 是干什么的?

WindowManagerGlobal 是一个全局单例对象,它是 Android 系统中 WindowManager 的管理类。它负责管理所有的窗口以及与窗口相关的一些属性和状态,例如屏幕方向、屏幕亮度等。WindowManagerGlobal 的主要职责包括:

  1. 提供了一些接口,用于向 WindowManagerService (WMS) 添加、更新和移除窗口。
  2. 维护了一个窗口列表,用于跟踪当前系统中存在的所有窗口。
  3. 提供了一些接口,用于查询当前系统中的窗口,例如通过窗口类型、窗口所在的应用程序等进行查询。
  4. 提供了一些接口,用于调整系统的一些属性和状态,例如屏幕方向、屏幕亮度等。

总之,WindowManagerGlobal 是 Android 系统中 WindowManager 的核心管理类,负责管理整个系统中的窗口,保证系统窗口的正常显示和管理。

mWindowMap 为什么使用 HashMap 好处在哪?

mWindowMap 采用 HashMap 的主要好处是它允许快速的查找和访问窗口对象。HashMap 是一种基于哈希表实现的 Map 接口,它将键映射到值。在 HashMap 中,键的哈希值被用来确定这个键的桶位置,每个桶存储一个键值对。因此,当需要查找某个窗口对象时,可以根据窗口 ID 通过哈希函数快速定位到对应的桶,然后再通过比较窗口 ID 找到对应的窗口对象。这种查找方式的时间复杂度是 O(1),非常高效。此外,HashMap 还可以存储键值对,因此 mWindowMap 可以用来存储窗口 ID 和对应的窗口对象。这样,当需要访问某个窗口对象时,只需要通过窗口 ID 查找对应的窗口对象即可。

Android 是如何保证mWindowMap 的线程安全的?

在 Android 中,mWindowMap 变量是在 WindowManagerService 类中定义的。WindowManagerService 是 Android 系统中的一个系统服务,它负责管理所有窗口的显示和操作,因此 mWindowMap 变量的访问和修改都是在 WindowManagerService 的上下文中进行的。

WindowManagerService 内部会采用一些方法来保证 mWindowMap 的线程安全性,其中比较重要的有以下几点:

  1. 对 mWindowMap 进行加锁,保证在同一时刻只有一个线程能够对 mWindowMap 进行读写操作。在 WindowManagerService 内部,mWindowMap 的访问和修改都是在互斥锁的保护下进行的,因此能够保证线程安全。

  2. 在多线程环境下,对 mWindowMap 的读写操作都是在主线程中进行的。例如,当一个应用程序需要创建、更新或者删除一个窗口时,它会向 WindowManagerService 发送消息,由主线程来处理这些消息。由于 Android 应用程序中的主线程是单线程的,因此能够保证 mWindowMap 的线程安全性。

综上所述,Android 系统通过采用互斥锁和主线程的方式来保证 mWindowMap 的线程安全性,从而保证了所有窗口的正确显示和操作。

为什么要使用实现类的写法?

可以保证PhoneWindow和WindowManagerImpl 单独发展而不是耦合在一起

Activity onStart可见嘛?可见,但是是Activity可见,View在onStart时候还没有设置,onResume才将View设计进入 addView

那么也可以解释清,为什么livedata要在onResume才进行回调

VSYNC 是怎么实现的?

这个地方最开始看的时候没有注意到

 这个地方最开始以为是Handler,其实并不是,是一个申请VSYNC的类

Choreographer::postCallbackDelayedInternal 里为什么直接通过Handler发送消息。不应该等VSYNC信号回调么?

Choreographer::postCallbackDelayedInternal 方法内部确实通过 Handler 来发送消息,而不是等待下一次 VSYNC 信号回调。这是因为 Choreographer 需要尽可能地保证应用程序的帧率稳定性和流畅性,在下一次 VSYNC 信号到来之前,需要尽快处理任务队列中的任务。而等待下一次 VSYNC 信号回调的时间可能会很长,这样会导致任务队列中的任务积压过多,最终影响应用程序的帧率稳定性和流畅性。

因此,Choreographer 内部采用了一种机制,即在每个 VSYNC 信号到来时,都会执行一次 CALLBACK_TRAVERSAL 回调函数,处理任务队列中的 CALLBACK_TRAVERSAL 类型的任务。但是,如果任务队列中的任务数量过多,每个 VSYNC 信号到来时都无法处理完毕,这时就需要通过 Handler 来发送消息,尽快处理剩余的任务。

在 Choreographer::postCallbackDelayedInternal 方法中,如果任务队列中的任务数量超过了阈值,就会通过 Handler 发送 CALLBACK_TRAVERSAL 消息,以便尽快处理任务队列中的 CALLBACK_TRAVERSAL 类型的任务。如果任务队列中的任务数量未超过阈值,就会将提交遍历任务的操作延迟一段时间,并延迟执行 CALLBACK_TRAVERSAL 回调函数中的任务。这样做的目的是为了尽量保证应用程序的帧率稳定性和流畅性。

也就是说超过阈值会直接执行,否则存入对列

onStart 生命周期还没有addView为什么可以弹出 Dialog?

onStart 生命周期虽然还没有 addView,但 Dialog 并不是通过添加视图的方式实现的,而是通过创建一个新的 Window 来实现的。 DialogWindow 会覆盖当前 Activity 的 Window,并且具有自己的视图层次结构和绘制流程。因此,即使 Activity 的视图层次结构还没有被创建,也可以弹出 Dialog

使用Object锁和使用this锁都可以实现线程同步,但是它们的作用范围不同。

this锁是指当前对象的锁,它只能锁定当前对象的方法或代码块。而Object锁可以锁定任何对象,不仅仅是当前对象。

在多线程编程中,为了避免出现竞态条件和数据不一致等问题,我们需要对共享资源进行同步操作。如果使用this锁,那么只有当前对象中的所有同步方法或代码块会被锁定,而如果有其他对象同时访问该共享资源,就无法保证线程安全。而使用Object锁则可以锁定任何一个对象,包括共享资源本身,从而保证线程安全。

此外,使用this锁容易出现死锁问题。因为如果一个线程获取了当前对象的锁,又试图获取其他对象的锁,就有可能造成死锁。而使用Object锁则可以避免这个问题,因为每个线程可以获取不同的锁,从而避免了死锁。

因此,当需要保证共享资源的线程安全时,使用Object锁更加合适。而当只需要锁定当前对象的方法或代码块时,使用this锁更加适合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值