a house in the woods

Hi, nice to meet you.

  1. 1. 前言
  2. 2. 过程
  3. 3. 总结

前言

前段时间,华为发布了Harmony-Next。据介绍,它是完全区别于安卓的自主开发的系统,不支持运行apk
那作为一名flutter的开发者,自然也关心flutter能否支持鸿蒙应用的开发。在flutterissues里,flutter的开发者表示没有官方支持鸿蒙系统的计划,但开发者可以通过实现embedder去自行支持。
于是这激起了我去了解embedder的兴趣。

过程

主要是通过阅读go-flutter的源码去了解的,后来了解了另外一个项目flt,作为对照来加深对embedder的了解。
他们最明显不同的地方是,前者是go实现,使用glfw框架,使用opengl做渲染的;后者是rust实现,使用crossterm库,直接在终端渲染。
它们分别对应的是flutter engine支持的其中两种渲染配置,一种是opengl(直接调用openglapi,使用gpu硬件);另一种是software(生成image像素buffer,再通过SoftwareSurfacePresentCallback,将数据传出,交由host自由渲染)。实际上flutter还支持vulkanmetal两种渲染器,这还表明默认使用的skia(或未来的impeller)绘图库支持硬件和软件的绘制方式。

embedderflutter engine定义的一个abi,目标是在对应的平台上运行flutter engineflutter engine本身是跨平台的(因为正如上面所说,skia是跨平台的),核心只是提供了渲染界面和与flutter engine与通信的功能。

通信方面,embedder定义了一些callback需要host去实现,由flutter engine调用,而host则可以直接调用flutter engine提供的方法。

可以看到flutter engine,主要调两类callback,一种是渲染相关的,一种是在某时刻将要在engine内执行的任务(FlutterEngineTask)。而为了执行callback或者说是处理事件,embedder需要提供一个event loop
其实事件循环如果只是简单的实现,没有想象中那么复杂。go-flutter使用的是glfw类似sleep的机制,主线程休眠一段事件,等待engine线程或者本身glfw的事件,然后再去处理;而flt则是使用mpsc的消息模型,使用receive等待,收到一条信息以后,就直接处理。

因为FlutterEngineTask都会有一个触发时间,所以每次循环以后只会把到时间的任务,传回给engine进行处理。

系统相关的信息,比如窗口大小的改变,鼠标指针的交互,flutter engine则分别都有对应的方法(FlutterEngineSendWindowMetricsEvent.FlutterEngineSendPointerEvent),让host通知到自己。

其他的一些事件是通过channel的方式,而这个channel跟我们写的flutter plugin里用到的channel是同一个东西。比如go-flutter在处理键盘操作时,用到是flutter/keyevent这个channel,跟我们写的插件不一样的地方是,这个名字是官方定义的,也可以说使用的是官方的键盘插件。

总结

以上就是阅读两个embedder实现源码后的一些所得,填补了一点这方面的空白。这两个项目的代码量都不算很多,也比较易懂,虽然都是试验性质的,但至少可以通过它们认识到embedder并没有想象中那样的复杂。

ps: 这篇文章只是日记或者学习备忘的性质,没有什么深刻的见解,真知灼见应该只有真正动手去做的时候才会获得。

This article was last updated on days ago, and the information described in the article may have changed.