关闭带抽屉模式TMultiView与粘性服务的Delphi安卓应用为何出现ANR
问题根因
- Delphi 11 对FMX的TMultiView组件抽屉模式的渲染逻辑做了调整,窗口销毁时会异步等待侧边抽屉收起动画完成,才会释放组件资源
- 当前销毁逻辑在FormDestroy中直接调用stopSelf停止粘性服务,此时TMultiView的动画回调仍持有应用主线程消息队列引用,服务停止后应用进程未完全退出,残留的消息回调无法被触发,系统会判定应用无响应触发ANR
- Panel模式下TMultiView无动画过渡逻辑,销毁时同步释放资源,因此不会出现时序冲突
- 原有代码未主动调用
UnBindService,服务绑定连接泄漏也会加重该问题
解决方案
方案1:调整销毁时序(推荐)
先解除服务绑定、停止服务,再关闭主窗口,不要在FormDestroy中处理服务销毁:
procedure TForm1.btn1Click(Sender: TObject); begin // 先解除服务绑定 FService.UnBindService; // 停止服务 FService.LocalService.JavaService.stopSelf; // 短延迟等待TMultiView资源释放后再关闭窗口 TThread.CreateAnonymousThread(procedure begin Sleep(100); TThread.Synchronize(nil, procedure begin Close; end); end).Start; end;
删除FormDestroy中的FService.LocalService.JavaService.stopSelf代码。
方案2:禁用TMultiView关闭动画
不需要抽屉收起动画的场景下,可直接关闭TMultiView的过渡动画,规避销毁等待逻辑:
procedure TForm1.FormCreate(Sender: TObject); begin // 禁用抽屉模式的过渡动画 mltvw1.AnimateOptions := []; // 原有服务绑定逻辑 FService := TLocalServiceConnection.Create; FService.OnConnected := ServiceConnected; FService.BindService('ServiceTest'); end;
方案3:临时使用Panel模式
如果上述两个方案不适用,可暂时切回Panel模式,等待官方后续补丁修复该组件的销毁时序bug。
内容的提问来源于stack exchange,提问作者Ole Mortensen
相关产品推荐
相关产品推荐

