前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么flutter可以跨平台

为什么flutter可以跨平台

作者头像
韦东锏
发布2022-11-07 13:09:48
2.4K0
发布2022-11-07 13:09:48
举报
文章被收录于专栏:Android码农Android码农

团队开发的第一款flutter app即将上线了,也是职业生涯第一个正式的flutter app,现在回过头来,再来回顾下,为什么flutter可以实现跨平台,也算是为我自己解惑,解答这个问题,还是要看flutter的架构设计

flutter的架构

了解flutter的架构,用下面一张图片就可以了,相信很多人都有看过,一共有三层

Embedder

首页,最下面的是嵌入层(Embedder),嵌入层作为一个flutter应用入口,可以与原生底层操作系统进行交互,可以访问系统渲染,输入,消息总线,线程创建等各个系统的底层能力,嵌入层在是根据不同的平台单独实现,实现语言也不一样

平台

语言

备注

Android

Java C++

Kotlin语言,其实也是运行在Java虚拟机上

ios macOs

Object-C Object-C++

Windows

C++

Linux

C++

由于flutter是开源的,我们也可以去github上查看嵌入层的源码:https://github.com/flutter/engine/tree/master/shell/platform

可以把嵌入层理解成一个壳,flutter的应用本体是一个模块,套一个Android的壳,就是一个Android的应用,套一个ios的壳,就是ios的应用

engine

引擎层是flutter的核心部分,核心api的底层实现,比如图形绘制、文本布局、网络请求、io操作,dart运行环境创建等; 引擎层也会把底层的C++包装成Dart的代码,给UI层调用 github上可以看到引擎层的源码,https://github.com/flutter/engine/tree/master,主要是由C++跟dart来实现的

框架层

最上面的就是框架层了,通俗的可以理解为UI层,也是日常开发接触的层级;最上面的是Material跟Cupertino库,提供符合Material跟ios的设计规范,目前团队开发的app,最顶层用的统一是Material; 然后就是widget层,这里就是日常开发的大量耗时工作量地方,开发各个页面的widget,所以说,在flutter,一切皆widget 再往下就是渲染层,用于基于widget树生成渲染树,还有底层的基础层,这块在实际开发中,很少直接打交道

flutter用一个跨平台的开发语言Dart来开发UI层,然后核心功能,用C++实现,最后用嵌入层做一层包装,适配各个不同的平台上使用,由于UI部分,都是在框架层,从而实现跨平台实现;另外由于flutter是直接跟原生接口打交道,所以在性能上也会媲美原生app

渲染机制

上面提到的engine层,有个很重要的部分就是图形渲染,所有的widget最终的目的,都是为了绘制在屏幕上,这块的底层实现就是依靠Skia,Skia也是开源库,同时也兼容了多个平台,可以看下skia在Wikipedia上描述,基本兼容各主流的平台了

在github上,可以看到skia的源码:https://github.com/google/skia,大多数是C跟C++

所有flutter UI层的代码,都是dart语言编写的,在发布的时候,会编译成native语言,然后交给Skia去渲染,可以看下目前开发的app的apk的反编译后的包体目录

我们写的dart的代码,打包成libapp.so,整个flutter框架,打包成了libflutter.so,都变成底层语言了

所以flutter有个很大的特性,每次flutter是SDK大版本更新,只要打包环境的flutter版本更新下,最终生成的安装包就可以包含新的特性了,而不依赖Android系统或者ios系统的更新(当然有利也有弊,缺点是包体变大了,会大几兆)

跟原生平台交互

有时候,难免碰到flutter需要调用原生的功能和方法,官方提供了一个MethodChannel的方法,可以方便的实现跟原生交互,包括调用原生的方法,接口返回结果等

可以看到MethodChannel的核心实现是在engine层 跟原生交互,也需要各个原生各自适配,比如这次团队开发的地图的POI搜索,由于使用的高德官方的flutter地图插件,不支持POI搜索,就需要flutter用methodChannel发起一个方法调用,ios跟Android接受这个方法,各自集成原生的地图SDK,然后通过原生的SDK调用POI功能,再把结果返回给flutter

渲染原生的UI

整个flutter的框架,其实是一个独立的整体,跟原生是独立的,那有些功能,原生已经有成熟的实现了,flutter为了避免重复实现一套,希望可以直接用原生的UI展示在flutter上面 flutter为了解决这个问题,使用两个特定的widget来实现 (AndroidView and UiKitView),实现代码大致如下

代码语言:javascript
复制
if (defaultTargetPlatform == TargetPlatform.android) {
  return AndroidView(
    viewType: 'plugins.flutter.io/google_maps',
    onPlatformViewCreated: onPlatformViewCreated,
    gestureRecognizers: gestureRecognizers,
    creationParams: creationParams,
    creationParamsCodec: const StandardMessageCodec(),
  );
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
  return UiKitView(
    viewType: 'plugins.flutter.io/google_maps',
    onPlatformViewCreated: onPlatformViewCreated,
    gestureRecognizers: gestureRecognizers,
    creationParams: creationParams,
    creationParamsCodec: const StandardMessageCodec(),
  );
}
return Text(
    '$defaultTargetPlatform is not yet supported by the maps plugin');

原生渲染大致原理如下 1、拷贝原生视图的渲染纹理,在flutter渲染的时候,交给flutter去渲染 2、flutter接收到用户的点击事件,转换为原生输入事件,传给原生控件

可以知道底层实现,也是类似MethodChannel,而且目前仅支持ios跟Android,不过在技术上,也是可以支持Mac跟window,官方有可能后续会支持,有个缺点就是,这种实现会带来比较大的性能跟资源开销

总结

flutter可以跨平台,关键是跟他的架构设置有关,自己实现了dart语言,包括整个engine层,再结合嵌入层的壳效果,可以轻松的实现跨平台。 由于flutter的框架设计的很完善,大多数开发,基本都是跟widget打交道,不需要涉及底层和平台特性;不过实际开发中,还是会碰到不少不同平台的特性问题,这个是另外一个话题了,再次有空继续展开...

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-05-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android码农 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • flutter的架构
    • Embedder
      • engine
        • 框架层
        • 渲染机制
        • 跟原生平台交互
        • 渲染原生的UI
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档