Skip、Compose、Flutter和RN

news2024/9/27 23:40:37

哈喽,我是老刘

前几天看到一个新的跨平台框架Skip,它的底层技术方案是转译。
感觉还挺巧的,因为不久前刚刚做了一个内部分享,就讲到了虚拟化的转译方案。
其实跨平台开发的技术和虚拟化的技术有很多相通的地方。
正好本文就把跨平台开发的三种技术方案盘点对比一下。
话说6年前我们刚开始选择Flutter作为跨平台框架的时候,还没有Compose、Skip这些选项。
所以当时做出选择并不难,如果放到今天可能选择困难症就要犯了。

跨平台的三种技术方案

我们知道,跨平台开发的目标就是一套代码多个平台使用。
但是不同系统平台提供的编程语言、SDK等都是截然不同的,于是为了让同一套代码在不同平台能跑起来并且能绘制UI界面,就产生了不同的技术方案。

1、套壳

这里的套壳可不是操作系统的套壳,这里说的其实是一种中间层方案。
这种方案最典型的代表就是RN。

image.png


从上面架构图中可以看出来,RN使用JS开发页面和逻辑。
然后把页面相关的信息传递给原生的RN模块。
原生的RN模块把页面的内容转换为原生的各种组件,然后交给原生SDK进行渲染。

中间层是软件工程中最常用的一种解决方案,其最大的好处就是灵活、省事。
有了RN Android和RN iOS两个中间层,就可以在其上随意搭建自己的页面框架了。
这样基本不需要考虑底层系统带来的影响,理论上一切差异都可以在中间层搞定。
当然在实际的实践中做不到这么完美,不过也足以满足工程应用。

当然中间层也有它固有的缺陷。
最大的问题就是性能的损失,从RN来看性能的损失来源于以下几个方面。
中间层本身的消耗
中间层肩负着上下层转换的工作,这本身就会带来内存和CPU等运行期资源的消耗。
相对于原生开发来说,这种损耗是额外增加的。
在客户端这种对流畅性非常敏感的应用场景下,也很容易造成用户体验下降。

上下层通信造成的延迟
要知道,页面不是一次渲染就放在那不动了。
随着用户的操作,页面要随时进行更新。
这就涉及到了上下层的通信。
比如用户在页面上点击了按钮,需要把点击事件从原生SDK传递给JS页面。
JS页面响应点击后也需要把页面的变化传递给原生SDK。
这种跨编程语言运行时的通信,比原生组件和原生SDK间的通信要慢很多。
如果碰到用户拖动一个页面元素移动的场景,比如把阅读App中书架上一本书拖动到另一个位置。
这时用户手指每移动一个像素,就需要进行一次通信。
RN这类框架在面对这类场景时就容易出现比较明显的卡顿。

正式因为中间层方案的这些缺陷,因此才有了后面那些更复杂的解决方案。

2、自定义绘制引擎

Flutter可以说是这种方案的典型代表。

image.png

从上面架构图中可以看出来,Flutter重写了一套SDK用以代替原生的SDK。
其实图中没有画出来的是在SDK和Skia引擎中间还应该有一个Flutter 引擎层。
通常SDK只是给开发者提供一个接口。
基于SDK开发出来的页面需要经过Flutter引擎的处理才能传递给Skia进行绘制。
所以简单来说就是Flutter重建了一整套的UI体系。

这样做最大的好处就是Flutter可以做到和原生完全一致的架构。
自然也就没有了中间层方案的性能损耗。
这也是为什么Flutter可以做到媲美原生的性能的根本原因。
而随着Impeller等新一代渲染引擎的投入使用,Flutter在性能上超越原生也是非常有可能的。

但是要记住,每个技术框架都是一把双刃剑,它在解决一些问题的同时,也带来了新的问题。
自带引擎虽然能带来众多的好处,但是也有其代价:
开发成本
庞大的Flutter引擎需要投入大量的人力和资源进行开发和维护。
来看下面这张图,这是2021年的时候Flutter项目的截图

image.png

可以看到关闭了5万多个issue,还有1万多个没有关闭。
所以也就不难理解,为什么开发者圈子里对Flutter最大的担心是被官方放弃了。

除了成本问题,自定义引擎还有一个硬伤

无法调用系统功能
前面说的中间层方案,因为最终调用的还是系统级的SDK,所以可以很方便的调用系统的相关功能,只是需要考虑不同系统的差异性问题。
但是以Flutter为代表的自定义引擎方案,就没有这种优势了。
不同系统上只能通过系统的SDK调用系统功能。
比如Android上只能基于Android SDK调用手机的定位、相机等功能。
Flutter的整套体系都是自定义的,而且Dart语言也无法直接调用Java体系的SDK。
这就造成了Flutter本身只能是一个UI系统,当我们的App需要用到系统的各种功能时,Flutter只能通过一些外部的手段解决。
当然,Flutter通过channel机制已经可以比较方便的调用原生系统的功能了。
但是如果是碰到摄像头实时预览这类数据量很大的功能,仍然会有性能方面的损耗。

自定义引擎的方案的优缺点说完了,这里要提一下Compose。
本质上Compose也属于自定义引擎方案,它的架构如下:

image.png

对比Flutter,它的主要差异是为不同的系统平台定义了针对性的UI框架。
这样做的好处是比如在Android平台,他就直接算是原生开发了。
但是这样的代价就是不能做到真正意义的一套代码多个平台运行。
因为你至少要为每个平台写一套UI。
如果你想要做到业务逻辑代码的跨平台,还需要在架构上进行比较精细化的设计。

那有没有一种方案,既能保留中间层可以灵活兼容不同系统差异的优势,又能拥有自定义引擎的高性能呢?
也是有的,那就是接下来要说的第三种解决方案。

3、转译

这里要说的就是Skip了。
它的架构简单来说就是用Swift UI写APP。
在iOS上就是原生项目,直接可以运行。
在Android上会有一个转译工具,工具会把Swift UI项目转译成Kotlin Compose项目,然后就变成了Android的原生项目了。
架构如下:

image.png

这种方案本质上就是写一套iOS代码,然后通过工具翻译成不同平台的原生代码。
所以你最终得到的是多套不同平台的原生代码。
这样的好处是显而易见的:性能无缺,功能完备。
但是我并不是太看好这个框架,或者说我对转译这条路是有一定的疑虑的。
我觉得主要有三个问题需要解决:
编程语言层面的映射问题
记得早年做网络安全的时候,我们就有工具能把exe文件转译成c代码。
看起来很强大很美好是吧?
但其实转译出来的c代码和你一开始写的c代码是有很大差异的。
要明白,转译工具本身也是一个程序,它不可能像人一样先理解被转译代码的逻辑,然后用新的代码再实现一遍。
它的工作原理简单来说就是按照固定的映射关系去进行转换。
那转化后的代码逻辑能保证和原来的完全一样吗?
其实很难,因为不同语言的设计思想可能差异很大,你如果不能理解代码的逻辑,只是简单的映射其实很多功能是很难实现的。
举个例子,如果把函数式语言中的闭包转换为一个不支持函数式编程语言的代码,要如何转化呢?

SDK框架的映射问题
语言的转译只是其中一个问题,还有一个问题是功能组件的转译。
比如iOS中的.onAppear和.onDisappear,再比如iOS中的众多动画效果。
这些效果单独拿出来在compose中都能实现相同的效果,但是把整个框架映射过去就是另一回事了。
更不要说随着iOS和Android系统和sdk的升级,带来的不同版本间对应关系的问题。

三方库的管理
我们开发一个稍微大型一些的项目都需要用到三方库。
即便系统SDK的映射能完美的解决,但是用到的三方库肯定是没办法映射过去的。
这时候就需要把一些代码拆分出来分别管理了。
这也是一个项目层面需要考虑的难点。
这部分就不展开细说了,有项目经验的同学应该能很容易理解。

好了,前面说了我觉得这个解决方案的主要问题和难点。
接下来说说我认为这种方案未来的发展方向。

转译方案的未来

对比一下前面介绍的三种跨平台技术方案。
中间层方案因为其架构上固有的缺点,已经逐步被自定义引擎的方案取代其主流地位。
以Flutter为代表的自定义引擎方案目前被工程界广泛接受。
转译这种技术本身其实已经出现很多年了,但是由于转译工具本身的能力限制,一直没有成为主流。
不过当下AI的发展给转译这条路带来了新的希望。
转译工具在功能上一直无法突破的一个底层原因是它无法去理解被转译代码的逻辑,所以只能按照固定套路去转译。
但是当前AI已经能在很大程度上理解代码的功能逻辑了。
(注意当前的大语言模型并不是真正的建立逻辑思维,和一个程序员去理解代码逻辑还是有区别的)
基于AI的,建立在理解代码逻辑基础上的转译工具,可能是转译方案未来的发展趋势。

image.png

我们展望一下,如果我们能基于大语言模型,训练一个把Swift UI转换成Compose或者反过来的AI工具。
那么这种转化其实本质上就相当于一个程序员把Swift UI的代码用Compose重新实现了一份。
转译这种技术方案的优势就能彻底发挥出来,相当于一次写了两套甚至多套原生代码。
这样的话转译的技术方案就能和自定义引擎的方案分庭抗礼并驾齐驱了。
更进一步,最初始的那套Swift UI代码也交给AI完成。
好吧,我们程序员差不多可以失业了。

image.png

总结

前面我们盘点了目前跨平台开发框架的主流技术方案。
其中转译方案目前虽然不是主流,但是随着AI的发展,未来潜力还是很大的。
立足当下,我仍然认为Flutter是当前跨平台的最佳选择。
即便未来转译方案真的能有突破性的进展,在端一致性等方面Flutter这样的独立引擎方案仍然具备优势。
另外,如果转译方案能有突破,那把Flutter代码翻译成原生代码似乎也是不错的选择。

好了,如果看到这里的同学有学习Flutter的兴趣,欢迎联系老刘,我们互相学习。
点击免费领老刘整理的《Flutter开发手册》,覆盖90%应用开发场景。
可以作为Flutter学习的知识地图。
覆盖90%开发场景的《Flutter开发手册》icon-default.png?t=O83Ahttps://mp.weixin.qq.com/s?__biz=MzkxMDMzNTM0Mw==&mid=2247483665&idx=1&sn=56aec9504da3ffad5797e703c12c51f6&chksm=c12c4d11f65bc40767956e534bd4b6fa71cbc2b8f8980294b6db7582672809c966e13cbbed25#rd

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2167483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

轻量级日志管理系统SpringBoot3+Loki+grafana的使用实例

目录 文章目录 目录1、简介2、SpringBoot3应用发送日志到Loki2.1、基本介绍2.2、添加依赖2.3、配置文件application.yml2.4、创建logback配置2.5、添加日志示例2.6、运行SpringBoot3 3、在grafana中查看日志3.1、登录grafana3.2、查询日志3.3、查询我们的SpringBoot发送过来的日…

Linux部署python web项目Flask + gunicorn + nginx

文章目录 一、安装python&使用虚拟环境二、python程序重要参数加密2.1 非对称加密(RSA)2.2 生成密钥对2.4 以连接数据库参数加密为例2.4.1 工具类RSA.py 三、一个简单的Flask项目四、安装配置gunicorn4.1 安装4.2 启动/配置(选择eventlet)4.2.1 命令…

随机信号介绍

一、信号分类 1.1 确定性信号 能够以确定的时间函数表示的信号,比如: 1.2 随机信号 也成为不确定信号或者随机过程,不是时间的确定函数。下面为随机信号的一个样本: 二、随机变量 2.1 定义 随机变量是指变量X的取值由每次随机试验的结果决定。 如果每次随机试验的结果…

JS封装函数转换时间案例

<script>let time prompt("请输入需要转换的秒数总数")function getTime(x) {let h parseInt(x / 60 / 60 % 60)let m parseInt(x / 60 % 60)let s parseInt(x % 60)h h > 10 ? h : 0 hm m > 10 ? m : 0 ms s > 10 ? s : 0 sreturn [h, …

CorePress Pro 网站加载慢 WordPress

一般来说是你用了「CorePress天气模块」 解决方案&#xff1a;这个插件从你右侧边栏里删掉就可以了&#xff08;上方的图中已经是删掉后的效果了&#xff09; 寻找加载时间长的原因&#xff1a; 谷歌浏览器F12->网络->打开录制->ShiftF5 得出结论&#xff1a;和风天气…

【JavaEE】数据链路层协议和DNS

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 &#x1f45c;一.以太网 以太网&#xff08;Ethernet&#xff09;是一种局域网技术&#xff0c;它定义了开放系统互连&#xff08;OSI&#xff09;模型中的物理…

【Pytorch图像+序列双输入网络源代码】

Python&#xff0c;Pytorch构建双输入网络&#xff0c;图像序列双输入&#xff0c;进行二分类。 如何基于Pytorch构建双输入的网络是曾经长时间困扰本人的问题&#xff0c;现已弄明白。本程序示例是一端输入图像&#xff0c;一端输入序列。 整体工作如下&#xff1a; 1、加载数…

CSS清除浮动的多种方法

目录 非 VIP 用户可前往公众号回复“css”进行免费阅读 给浮动元素的祖先元素加高度 给 div 写一个 clear:both; 属性(margin 失效) clear:both; 隔墙法 clear:both; 内墙法 父级 div 定义伪类:after 和 zoom(推荐使用) overflow:hidden;(能够让 margin 生效) 非 …

机器学习-KNN分类算法

1.1 KNN分类 KNN分类算法&#xff08;K-Nearest-Neighbors Classification&#xff09;&#xff0c;又叫K近邻算法。它是概念极其简单&#xff0c;而效果又很优秀的分类算法。1967年由Cover T和Hart P提出。 KNN分类算法的核心思想&#xff1a;如果一个样本在特征空间中的k个最…

【机器学习】——线性回归(自我监督学习)

文章目录 1. 线性回归的定义2. 线性回归的模型3. 线性回归的核心思想4. 线性回归的求解5. 线性回归的假设6. 模型评估7. 线性回归的优缺点8. 线性回归的扩展9. 线性回归的实际应用10. 示例代码&#xff08;Python实现&#xff09; 线性回归详细介绍 1. 线性回归的定义 线性回归…

【已解决】Ubuntu 24.04 修改 ssh 连接端口无效

用编辑器打开 /etc/ssh/sshd_config 文件 sudo vim /etc/ssh/sshd_config将 Port 22 改为你想要的端口号&#xff08;这里演示就设置为4080&#xff09; 用编辑器打开 /lib/systemd/system/ssh.socket 文件 sudo vim /lib/systemd/system/ssh.socket将 ListenStream22 中的 2…

Windows 10 系统安装 FFmpeg 查看、转换、编辑音频文件

1、FFmpeg官网&#xff1a;FFmpeg 点击下载 可以选择下载full版本 下载之后解压到指定目录&#xff0c;在系统环境变量 Path 里面新增环境变量 打开CMD终端运行 ffmpeg -version 查看是否安装成功。 2、基本命令 查看音频基本信息 ffprobe 1.mp3 ##输出 [mp3 000002ab334405…

Xcode16 iOS18 编译问题适配

问题1&#xff1a;ADClient编译报错问题 报错信息 Undefined symbols for architecture arm64:"_OBJC_CLASS_$_ADClient", referenced from:in ViewController.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit co…

<Java>String类型变量的使用

两边有一个string就是连接&#xff0c;否则做加法 ‘ ’是char&#xff0c;“ ”是string&#xff0c;char能做加法&#xff0c;string只能连接

STM32F407_05

RTC实时时钟 主要特性: 由于RTC实时时钟提供了三种时钟源可供选择(LSI,LSE,HSE) ,一般我们选择低速外部时钟源(32.768KHZ)来作为RTC的时钟源 另外&#xff0c;RTC实时时钟可以由系统主电源供电&#xff0c;但是也可以由备份电源供电&#xff08;系统主电源不工作时&#xff09…

微电网与大电网主动同步控制

前言 大电网正常运行时&#xff0c;微电网通过大电网得到正常的电压频率参数支撑&#xff0c;大电网故障时&#xff0c;微电网的电压和频率支撑需要通过分布式电源提供&#xff0c;从而保持自身独立运行。分布式电源提供的电压信息会因为自身的下垂特性随本地负荷的改变不断变…

leetcode331. 验证二叉树的前序序列化

序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时&#xff0c;我们可以记录下这个节点的值。如果它是一个空节点&#xff0c;我们可以使用一个标记值记录&#xff0c;例如 #。 例如&#xff0c;上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,…

【含文档】基于Springboot+Vue的高校师资管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

构建高效线上培训体系的知识库策略

在数字化时代&#xff0c;线上培训已成为企业提升员工技能、促进知识传递的重要手段。然而&#xff0c;如何构建一个高效、系统的线上培训体系&#xff0c;确保培训内容的准确性与时效性&#xff0c;是许多企业面临的共同挑战。其中&#xff0c;知识库作为培训资源的核心载体&a…

Arduino中实现定时器中断

1、使用MsTimer2库文件 使用之前需要先添加库 &#xff08;1&#xff09;实现功能 &#xff08;2&#xff09;代码 /*MsTimer2 is a small and very easy to use library to interface Timer2 withhumans. Its called MsTimer2 because it "hardcodes" a resolutio…