Win32窗口消息机制 x Android消息机制 x 异步执行

本文探讨了Android中的Handler机制与Win32窗口消息机制的相似之处,揭示了两者在消息传递与处理上的共通原理。文章指出,虽然环境不同,但核心思想一致:都是通过消息队列和循环来分发任务。

如果你开发过Win32窗口程序,那么当你看到android代码到处都有的mHandler.sendEmptyMessage和

private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_REPORT_PRIMARY_CLIP_CHANGED:
                    reportPrimaryClipChanged();
            }
        }
    };

不禁叹出,这不就是窗口消息机制吗?只是不关窗口的事了,然后分离出来消息机制。
sendMessage这个函数,我们查看窗口属性,改变窗口属性,通知窗口发生事件一切的一切仿佛都在调用这个函数。
WinProc这个消息处理函数,即使你在android的java代码里换了个名handleMessage,我们就认不出你来了吗?
就连Message也同样是一个整形,同时携带两整形参数(windows窗口消息c代码中可以放指针,android消息java代码另外还有Bundle,
Object引用参数,因为int不可以转换对象引用)

这样就很容易理解了:
在windows中,向一个窗口发送窗口消息,实质就是向创建窗口所在的线程的消息队列发送窗口消息,或阻塞等待处理或不阻塞。
在android中,向一个Handler发送消息,同样是在向这个Handler关联的线程的消息队列发送消息,并且不阻塞不等待处理。
在Win32窗口消息机制,消息在消息循环中分派。
在android中,Looper封装了这个消息循环以及消息队列,并在线程的TLS中存放其引用(指针),对于线程唯一存在。如果在实例
Handler时不指明Looper默认借用当前线程的Looper。Handler关联某一个Looper,一个Looper唯一关联一条线程。向Handler发送消息
就是向Looper的消息队列发送(入队)消息,线程必须执行Looper.loop消息循环,消息才能分派。

要注意就是:
窗口在Windows系统是系统范围的,我们可以利用窗口消息进行进程间通讯。而android的Handler却不是。
窗口在Windows系统在创建它的线程上处理消息,任何线程都可以创建窗口。而android的窗口(视图)只能在主线程创建和访问。
在android的消息机制中,还可以发送一个Runnable到某一线程的消息循环中执行,这点就仿如iOS的GCD中的dispatch_async代码块。

参看源代码:

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

Java异步线程执行代码块:

mHandler.post(new Runnable() {
     public void run() {
     // ....
     }
});

OC异步线程执行代码块:

dispatch_async(global_queue, ^{
     // ....
     });

 

转载于:https://www.cnblogs.com/bbqzsl/p/6360808.html

<think>我们正在讨论Android窗口管理中的窗口移除流程。根据用户提供的引用之前的问题,我们需要概述窗口移除的流程。注意,用户特别提到了ActivityRecordToken,但这次的问题是关于窗口移除的流程概述。 窗口移除流程涉及多个层次,包括应用侧的ViewManager接口系统侧的WindowManagerService(WMS)。根据引用[1],ViewManager接口定义了三个基本操作:addView, updateViewLayout, removeView。因此,窗口移除的入口是ViewManager.removeView()。 在Android系统中,窗口移除的流程可以概括为以下步骤: 1. 应用侧调用ViewManager.removeView()(通常通过WindowManagerImpl)来请求移除一个窗口。 2. 这个请求会传递到WindowManagerGlobal,它是整个进程内所有窗口视图的管理中心。 3. WindowManagerGlobal会通过ViewRootImpl来处理移除请求。 4. ViewRootImpl会通过IPC(通过IWindowSession)调用WMS的removeWindow方法。 5. WMS在接收到移除窗口的请求后,会执行一系列清理工作,包括: - 从窗口栈中移除该窗口 - 更新焦点窗口(如引用[2]所述,在窗口移除过程中会触发焦点窗口更新) - 释放与窗口相关的资源(如Surface) - 通知InputDispatcher移除该窗口的输入通道 6. 在应用侧,ViewRootImpl会处理窗口移除后的回调,如调用View的onDetachedFromWindow()。 另外,对于系统窗口(如状态栏、导航栏,引用[3]中提到的类型为TYPE_STATUS_BARTYPE_NAVIGATION_BAR),其移除流程也是类似的,但通常由系统进程(如SystemUI)发起。 下面详细描述关键步骤: ### 一、应用侧触发移除 当应用调用`WindowManager.removeView(view)`时,实际调用的是`WindowManagerGlobal.removeView(view, false)`。该函数会查找该view对应的ViewRootImpl,并调用其`die()`方法。 ```java // WindowManagerGlobal.java public void removeView(View view, boolean immediate) { ... int index = findViewLocked(view, true); ViewRootImpl root = mRoots.get(index); ... root.die(immediate); } ``` ### 二、ViewRootImpl处理移除 ViewRootImpl的`die()`方法会发送一个`MSG_DIE`消息到主线程Handler,最终调用`doDie()`方法。 ```java // ViewRootImpl.java void die(boolean immediate) { if (immediate) { doDie(); } else { // 发送异步消息,确保在主线程执行 mHandler.sendEmptyMessage(MSG_DIE); } } void doDie() { ... if (mAdded) { dispatchDetachedFromWindow(); } ... } ``` 在`dispatchDetachedFromWindow()`中,会通过`WindowSession`(IWindowSession)通知WMS移除窗口,并执行本地清理: ```java // ViewRootImpl.java void dispatchDetachedFromWindow() { ... try { mWindowSession.remove(mWindow); // mWindow是IWindow.Stub,即窗口的Binder标识 } catch (RemoteException e) { } ... // 调用View的onDetachedFromWindow mView.dispatchDetachedFromWindow(); ... // 清理资源 mWindow = null; ... } ``` ### 三、WMS处理窗口移除 在WMS中,`removeWindow()`方法会执行以下操作: 1. 根据传入的`IWindow`(即ViewRootImpl中的mWindow)找到对应的WindowState(代表WMS中的窗口状态)。 2. 从窗口栈中移除该窗口,并调整窗口层级。 3. 更新焦点窗口(如引用[2]所述,在窗口移除过程中会触发`updateFocusedWindowLocked`)。 4. 销毁窗口的Surface,并通知InputDispatcher移除该窗口的输入通道。 5. 释放WindowState及相关资源。 ```java // WindowManagerService.java public void removeWindow(IWindow window) { ... synchronized(mWindowMap) { WindowState win = windowStateMap.get(window.asBinder()); if (win != null) { win.removeIfPossible(); } } } ``` 在`WindowState.removeIfPossible()`中,会调用`removeImmediately()`执行实际移除。 ### 四、窗口移除后的回调 在应用侧,当`dispatchDetachedFromWindow()`被调用时,会触发View树的`onDetachedFromWindow`回调,允许应用执行清理工作。 ### 五、系统窗口移除 系统窗口(如状态栏)的移除流程类似,但通常由系统进程控制。例如,SystemUI在需要隐藏状态栏时会调用`WindowManager.removeView()`。 注意:系统窗口的Token通常由WMS在添加时创建(通过`WindowToken`),移除时也会一并销毁该Token(如果没有其他窗口使用)。 ### 流程图 窗口移除的总体流程可表示为: ```mermaid sequenceDiagram participant App as 应用进程 participant WMGlobal as WindowManagerGlobal participant VRI as ViewRootImpl participant WMS as WindowManagerService App->>WMGlobal: removeView(view) WMGlobal->>VRI: die() VRI->>VRI: doDie() VRI->>VRI: dispatchDetachedFromWindow() VRI->>WMS: mWindowSession.remove(mWindow) WMS->>WMS: removeWindow(WindowState) WMS->>WMS: 更新焦点窗口[^2] WMS->>WMS: 释放Surface, 移除输入通道 WMS-->>VRI: 操作完成(异步) VRI->>View: dispatchDetachedFromWindow() VRI->>WMGlobal: 移除ViewRootImpl记录 ``` ### 关键点 - **异步移除**:默认情况下,移除操作是异步的,通过发送消息到主线程队列执行,以避免在UI线程中直接执行耗时操作。 - **资源释放**:Surface的释放必须在WMS中完成,因为Surface由SurfaceFlinger管理。 - **焦点更新**:窗口移除后,WMS会重新计算焦点窗口(如引用[2]所述)。 通过以上流程,Android系统能够安全、高效地移除窗口,并保证UI的稳定性响应性。 相关问题: 1. 窗口移除过程中如何保证线程安全? 2. 如果窗口移除时正在执行动画,系统会如何处理? 3. 窗口移除后,为什么需要调用View的onDetachedFromWindow()方法? 4. 系统窗口(如Toast)的移除流程与应用窗口有何不同?</think>### Android窗口移除流程概述 Android窗口移除流程是窗口管理中的核心操作,涉及应用侧请求、系统服务处理资源释放三个阶段。以下是关键流程解析: #### 一、移除入口:ViewManager接口 窗口移除起始于`ViewManager.removeView()`调用,这是窗口操作的统一接口[^1]: ```java // 应用侧调用示例 WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE); wm.removeView(view); // 触发移除流程 ``` #### 二、核心处理流程 ```mermaid sequenceDiagram participant App as 应用进程 participant WMGlobal as WindowManagerGlobal participant VRI as ViewRootImpl participant WMS as WindowManagerService App->>WMGlobal: removeView(View) WMGlobal->>VRI: die(boolean immediate) alt 异步移除 VRI->>VRI: 发送MSG_DIE消息 VRI->>VRI: doDie()处理 else 同步移除 VRI->>VRI: doDie()立即执行 end VRI->>WMS: mWindowSession.remove(mWindow) WMS->>WMS: removeWindowLocked() WMS->>WMS: 更新焦点窗口[^2] WMS->>SurfaceFlinger: releaseSurface() VRI->>View: dispatchDetachedFromWindow() ``` #### 三、关键步骤详解 1. **应用侧请求**: - 调用`WindowManagerGlobal.removeView()`查找目标ViewRootImpl - 触发`ViewRootImpl.die()`方法,参数控制同步/异步移除: ```java // ViewRootImpl.java void die(boolean immediate) { if (immediate) { doDie(); // 同步移除 } else { mHandler.sendEmptyMessage(MSG_DIE); // 异步移除 } } ``` 2. **ViewRootImpl处理**: - 在`doDie()`中通过Binder调用WMS服务: ```java mWindowSession.remove(mWindow); // mWindow是IWindow.Stub ``` - 触发View树回调: ```java mView.dispatchDetachedFromWindow(); // 通知View释放资源 ``` 3. **WMS系统处理**: - 执行`removeWindowLocked()`核心操作: ```java // WindowManagerService.java void removeWindowLocked(WindowState win) { mWindows.remove(win); // 从窗口列表移除 win.mClient.asBinder().unlinkToDeath(); // 解绑Binder mInputMonitor.onWindowRemoved(win); // 更新输入系统 } ``` - 更新焦点窗口(引用[2]流程): $$ \text{updateFocusedWindowLocked()} \rightarrow \text{findFocusedWindow()} $$ - 释放Surface资源: ```cpp SurfaceControl::release(win.mSurfaceControl); // Native层释放 ``` 4. **系统窗口特殊处理**: - 状态栏/导航栏等系统窗口(如TYPE_STATUS_BAR[^3]): ```java // SystemUI移除状态栏示例 mWindowManager.removeView(mStatusBarView); ``` - WMS会校验`WindowToken`有效性,防止非法移除 #### 四、并发安全机制 1. **全局锁保护**: ```java final WindowManagerGlobalLock lock = mGlobalLock; synchronized(lock) { // 窗口树操作 } ``` 2. **线程约束**: - 必须在主线程调用`removeView()` - WMS内部使用独立线程处理Binder调用 #### 五、资源释放时序 $$ \text{应用资源} \rightarrow \text{WMS元数据} \rightarrow \text{Surface资源} \rightarrow \text{GPU内存} $$ 1. View.onDetachedFromWindow() → 释放Bitmap等资源 2. WMS移除WindowState → 释放窗口属性数据 3. SurfaceFlinger回收GraphicBuffer → GPU内存释放 --- ### 相关问题 1. **窗口移除过程中发生ANR会怎样处理?** 2. **如何确保异步移除时窗口状态的一致性?** 3. **系统窗口(如Toast)的自动移除机制如何实现?** 4. **View.dispatchDetachedFromWindow()中适合执行哪些清理操作?** 5. **窗口移除后InputDispatcher如何重新分配输入焦点?[^2]**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值