作者:Liu Taiju()Liang)
“ Dutter系列文章”将根据Flutter的技术实践和基于Flutter的技术实践和基于Flutter的坑的坑进行解释坑的技术实践和坑。第四端的设计和技术实践。本文是下一篇文章。谢谢您的阅读。
本文主要在桌面上的桌面上介绍了几个Flutterengine级别的错误。特定包含:
让我们向所有人介绍它。
MAC FlutterViewController被销毁后,实际上没有发布内存,并且会发生内存泄漏问题。在Mac方面的扑面业务。如果不处理,它将直接影响Mac侧Dutter的可行性:
一句话中的原因:
Mac -end Flutterengine的弱财产实施是不合理的。FlutterViewController持有FlutterEngine,后者持有指向FlutterViewController的薄弱财产。FlutterViewController试图在Dealloc过程中释放Flutterengine,但此时,在FlutterGengine中持有的薄弱财产,Fluttergine可以在FlutterGengine中持有FlutterGengine的财产。不再正确访问,导致释放过程和泄漏的故障。
以下结合了特定的实现,以简要说明所有人。
由于OC和C ++对象的生命周期管理的设计,Flutterenengine的内部对象保持稍微特别一些,如下图所示:
在正常情况下,在FlutterViewController退出后,它将通过调用Flutterenegine的setViewController触发Flutterengine损害。参考实现如下:
也就是说,在正常情况下,FlutterViewController DealLoc应触发369行代码操作,然后发布FlutterEngine Resources。但是,实际操作并非如此。当代码运行到359行时,请尝试判断(_viewController!= Controller)是否未建立。通过上述代码,我们知道控制器是目前为nil的外部对象;_viewController是一个薄弱的Proputher,在FlutterViewController将DealLoc进程输入到NIL之后。因此,在此过程中,我们想要的shutdownDownEngine方法未被调用。
解决问题后,处理方法非常简单。当FlutterViewController Dealloc.可以通过上层的OC动态特性实现,或直接修改FlutterEngine的重新分配时,您可以手动触发Flutterengine shutdownengine方法。
但是,这里的修改必须谨慎,请注意Flutteningine中关闭过程的完全恢复,否则我们可能遇到的第二个问题可能是:死锁。
当指甲最初处理上述“ Flutterengine泄漏”问题时,采用了一个相对简单的解决方案:在FlutterViewController DealLoc方法中,手动调用FlutterEngine提供的ShutdownGine方法手动触发相关资源释放。
通过该解决方案,在FlutterViewController退出退出后,内存确实会减少,但是发现在灰度期间,整个页面中偶尔会粘在整个页面上。通过简单地分析问题的链接并与暴力测试合作,我们已经恢复了问题在调试环境中,末尾,UI线程和栅格线处于开始,僵局后的线程状态大致如下。
UI线程状态:
栅格线:
一句话中的原因:
调用FlutterEngine关闭engengine的方法是不合理的。在关闭Engengine之前,您必须首先调用FlutterView的关闭方法以停止渲染过程。渲染过程正常停止后,您可以输入FlutterEngine资源发布过程,否则可能会发生上述僵局。
由于此问题是由不合理的呼叫引起的,因此不再深入分析特定的异常原因。有兴趣的学生可以根据上述线索进行检查。
在高层完成Flutterengine发布过程,首先致电FlutterView关闭,然后致电FlutternGine ShutdownEngine。
这个问题仍然是两个问题。处理问题1和问题2后,请参阅Flutterengine关闭过程。在破坏了FlutterViewController之后,它将做3件事:
经过一系列治疗后,测试发现内存泄漏和死锁问题基本上已经治愈了。但是,在内部灰度过程中,崩溃将出现在MacOS的低版本上,并且堆栈大致如下:
一句话中的原因:
与问题2相似,该问题也是由指甲泄漏问题引入的。进步;另一方面,由于MACOS OpenGL的低版本,它无法保护不完美过程中的关键链接,这将导致异常。
让我们对异常相关代码做出简短的答案,以避免其他学生再次遇到类似的问题。
1.在Flutterengine setViewController方法中,如果您处于发布过程中,则将调用Flutteropengenders setFlutterView方法并传递给NIL:
2. FlutterOpenglrenderer setFlutterView方法将释放输入参数时在内部维护的NSopengLcontext对象:
3.当grdirectContext对象破坏时,将执行FlutterEngine的基础实现。如果此时发布了OpenGL的相关对象,则崩溃将出现在MacOS(10.11,10.12)的低版本中:
因为问题的一部分是由指甲的上限触发的,所以处理相对简单。最后,我们删除了OpenGL呈现的所有MAC设备上的FlutterView(MacOS 10.14的先前版本)。阶段仅执行以下两个操作:
这个问题背景稍微复杂。如果您看一下,应该将此问题分为两个子问题。
第一个问题是,在某些Win7设备(X86 + X64)上,D3D11造成的崩溃,堆栈大致如下:
由于无法定位此问题,因此出现此问题的具体原因,而Flutter官员表示,他们对Win7设备的覆盖范围并不完美。因此,我们决定添加一些flutterengine的自定义,并强行通过弹奏页面通过Win7等旧设备上的“软解决方案模式”。
我认为它可以以这种方式绕过这个问题,但是不幸的是,该解决方案在Flutterengine中暴露了另一个错误:当使用“软解决方案模式”来渲染页面时,FlutterViewController关闭了,仅引起Windows Desktop RelistFilm。
一句话中的原因:
这个问题主要是因为在Flutterengine的内部关闭过程中,FlutterWindowsEngine指针尚未及时修改,以指向FlutterWindowSview对象,该对象在多线程中导致野生指针。因为野生指针导致了栅格窗格,以在破坏下输出绘图框架,并提高到它。导致异常。
定位时,我们通过增加辅助日志来加速问题定位过程。通过补充关键节点中的日志,我们很快找到了可疑点:
上图是问题之后的登录,我们可以通过日志获取以下密钥信息:
因为末端使用的窗口手柄为NULLPTR,这会导致残留阴影的问题。
补充说明:当调用C ++成员函数时,即使这已经是一个野生指针,只要成员函数无法访问该对象,就不会有内存访问异常。
修改Flutterengine的内部实现。当将FlutterWindowsView设备放置在SoftWarendererer模式下时,空的FlutterWindowsEngine指向它(因为GPU模式将具有异常输出,暂时没有进行修改):
通过这种方式,它可以确保在flutterwindowsview被销毁后栅格线程中的任务不会回电渲染界面:
2.2 Flutterplugin注册阶段野诗崩溃
在“+面板”业务的Flutter版本的Windows End中,Windows End出现了更多的崩溃案例,客户的总体崩溃率高达x%:
通过简单的分析,还原崩溃堆栈大致如下:
它可以从堆栈中获取两个重要的信息:
一句话中的原因:
Flutter为Windows平台提供包装层代码,其中包含一个单箱对象插件插件。它通过地图维护了颤音关节和注册人体之间的映射关系,以确保注册服务商和FlutterEngine保持一致。插件registrarmanager实现,即“单个案例机制”失败。问题是,当Flutterengine设备无法正确删除PluginRegistRarmanager中的绑定关系时,它会导致其内部维护到失败的指针地址,并且在崩溃中出现了崩溃再次访问。
让我们简要介绍分析过程。通过暴力测试,我们可以重现问题:
根据上图,可以确认出现崩溃,因为Flutterengine对象野生指针。在进一步定位插件时,发动机指针源可以位于Flutter :: pluginRegistRarmanager :: getInstance()- > getRegistrar()方法:
进一步分析了PluginRegistRarmanager的实施,我们可以看到MAP + EMPLECE方法是GetRegistrar内部需要的,以维持Flutterenegine地址和注册商之间的关系:
它将通过FlutterDesktopplugistrarsetDestructionHandler在底层引擎对象中注册该方法。当称为Flutterengine破坏时,将被称为,并将解除结合关系:
问题在于这个过程。如果pluginregistrarmanager不是一个真正的示例,而FlutterEngine只能保持有效的onregistrardestroy回调,那么当flutterengine是destructor时,某些flutterengine地址保存在pluginregistrarmanager对象中的某些flutterengine地址将不会删除。使用时会引起问题。
修改Flutterengine包装层插件插件实现以优化“单个情况”实现方案。管理单个生命周期的下层的下层,包装器层仅负责提供相关服务。
特定参考:
在Windows的扑波页面中,如果flutter窗口:
可以发现,颤抖页面的内容无法正常显示,画布是空白的。如果通过在白屏后触发颤音页面或拖动窗口来刷新颤音页面,则可以正常呈现内容。
这个问题相对清楚。飘动的窗户结束了一个错误。在更改窗口的可见性之后,应重新打开冲洗,以将最新视图绘制到相应的窗口,但是当前的过程尚未实现,从而导致上述问题。
这个问题已提交问题,临时指甲方面正在通过上层薪酬绕过此问题。在本地窗口的可见性变化后,我们手动通知颤音的一面以刷新当前的可见页面,从而触发重新启动。并避免问题。
以上是在飘落着陆过程中桌面处理的主要问题。从我们的实际经验中进行判断,尽管Flutter v2.10版本已正式发布了对Windows的支持。但是从稳定的角度来看,Mac侧面的表现毫无疑问是比Windows更好。如果还有其他团队可以尝试在桌面单端上使用Flutter,那么我们优先考虑推荐Mac侧。无论是开始阈值还是性能稳定性性能,它都比Windows侧更有利。
请注意[阿里巴巴移动技术],阿里的前沿移动干货和实践将为您思考!
原始:https://juejin.cn/post/7096737604795629599