聊 · Flutter

news2024/10/6 5:56:28

曾经的团队是国内最早投入Flutter框架怀抱的团队,后来又有机会负责起了Flutter相关项目,翻回以前写的文章,感慨良多,这是其中的一篇关于这些内容的闲聊。

| 导语Flutter相关的技术资源官网和网友都有过系统且细致的整理,因此这篇文章不是系统的介绍Flutter,而是把我的学习Flutter的一些感受记录分享,内容组织比较零散,想到哪说到哪,欢迎留言讨论。

前言

Dart是Flutter的编程语言,Flutter是Google的UI工具包,用于从单个代码库构建漂亮的本机编译的移动,Web和桌面应用程序。

接下来我们从Dart到Flutter,再到Flutter engine,聊一下我印象深刻的点。

聊·Dart语言:

并发

我一直在项目中反对组员直接使用_beginthread的多线程并发,因为很多人不考虑函数的可重入性,导致埋下许多坑,在我看来多线程弊大于利,于是严格要求大家只能用PostToXxThread的方式使用多线程。而我发现Dart对多线程并发的设计正是我所需要的,彻底解决了多线程加锁互斥的难题,相当于强制使用Post方式,即满足了并发的要求也解决了多线程最让人头疼的线程同步,真是填补了个大坑,Dart干得漂亮

单线程如何解决IO等耗时操作导致的无响应呢?推荐的做法是async-await方式,总体上Dart的async-await设计和JavaScript以及C#的设计大同小异,使用体验好。async-await的方式到了底层其实就是多线程(也不排除协程),但是如果想要像dart的这种async-await编写体验则必须让语言支持垃圾回收,因为在不支持垃圾回收的语言(如C++)是无法处理后await返回后栈对象或者this被释放的场景,因此类似C++语言目前只有“鸡肋版的async-await”。Dart runtime的线程模型基本和chromium高度一致。

空安全

我们通过C++实现了win/mac的跨平台,但是代码里大量的空指针保护代码让我很难受,有时有人忘写了指针判断导致崩溃也会让人很头疼,而Dart也很好的解决了这个问题:

这篇文章对Dart的空安全讨论非常深入:深入理解空安全 | Dart

在其中看到这段话也非常认同:“代码的健全性极大程度地决定了开发者对于自己的代码是否有自信。一艘 大部分时间 都在飘忽不定的小船,是不足以让你鼓起勇气,驶往公海进行冒险的”。

避空运算符是个非常好用的语法糖,但是也会导致很多逻辑缺失异常处理,降低代码鲁棒性,为此我们建议在项目中避免使用逼空运算符:

Dart不支持反射:

如果需要用到反射能力,可以使用代码生成思路实现,基于此思路也提供了相关的dart package: dart的反射

关于反射,有的语言默认全部方法支持反射,有的语言使用语法糖支持显式反射,而dart用代码生成方式支持反射(或者说不支持反射),确实比较出乎我的意料之外的。这说明2点,第一:dart重视性能和编译优化,第二:代码生成这种方式在dart体系中应多处出现。代码生成确实给了语言很大的扩展空间,dart编译器和运行时抛掉了反射,也可以更加专注于代码生成的优化和执行效率,也意味着坚实的走在类似C++极致性能的道路上(我也感觉是chrome里优化V8性能那波人被JavaScript的动态化折磨得不要不要的,为此在dart果断的砍掉了动态化的特性)。

 和其他语言交互:

因为要实现逻辑跨平台,我对Dart语言和其他语言的交互比较关注。Dart毕竟是一种全新的语言,无论设计理念多么先进都会苦于没有丰富的库,因此Dart也更注重和其他语言的通信。

Dart和C语言的交互比较直接:

Dart和Native (java/OC)交互提供了类型安全机制:

Pigeon是一个代码生成器工具,使Flutter和主机平台之间的通信安全,更轻松,更快捷。

果然,代码生成的思路体现在官方的不少库中。这也许也是从chromium里学到的经验吧,chromium里有大量通过脚本生成的代码。

聊·Flutter :

声明式UI

Flutter框架使用的编程范式 (flutter.dev)

Flutter倾向于采取了最新的技术方案,其中UI界面的核心设计模式参考了React对UI开发的探索模型,这一点在Flutter wiki上有多处进行谈论:


对于习惯了传统的UI模型思维方式来说,这种UI开发模式确实需要一段时间的熟悉。不过这种声明式编程方式确实是一种进步的探索,我想从多个方面对此设计进行思考:

  1. 声明式用户界面对渲染引擎层不友好,需要引擎对其做更多的优化(比如渲染引擎要自己计算哪个widget需要重新绘制),当渲染引擎的理论和实践发展到一定程度后,才会出现声明式用户界面框架。声明式用户界面的引擎也必将选择单独的渲染树的实现方式。
  2. 声明式用户界面一定程度上简化了UI开发的复杂度,不需要引入额外的静态语言描述界面结构(如web的html,qt的.ui文件),让界面的实现集中一处。是个重要的进步。我认为相关的代码逻辑能集中一处,就可以大大提高可读性(思考一个大需求的实现,改动了100行代码在10个函数好,还是改动了100个函数每个函数改了10行好)。
  3. 声明式用户界面的开发模式也避免了界面描述文件那种到处插入widget导致bug不易定位的问题。随处可以插入widget的开发方式自然是灵活的,但是灵活换来的代价是代码设计质量无下限,目前来看,编程的主流的方向是限制灵活性,走向约束和规范。
  4. 由于不需要解析界面描述文件,声明式用户界面首帧速度更优。客户端和web都能做UI界面,客户端比web最核心的2个优势就是首帧画面速度和内存占用。如果这两个优势没有了,那客户端同学就可以退出GUI层的开发任务了,专注于Console层了。
  5. 对于界面状态逻辑特别复杂的界面,声明式用户界面的编写规则更容易直观体现出界面和状态之间的关系,即 UI = f (state) 中的f是单独表达的。声明式用户界面的思维模型让界面里的状态和UI表达更为直观。
  6. 对于界面状态不在同一个widget的场景,或者界面状态离widget距离较远时,声明式用户界面反而比较麻烦。在实际的开发中,界面状态的数据大部分是放在比较集中的地方(如根widget),而界面小部件widget则是分散到界面树上,这就导致一个问题,实际开发中flutter的build的界面声明会特别巨大。为此flutter提供了InheritedWidget的特殊widget供孩子共享自己的状态,避免某一个build过于庞大。因此一个复杂界面的主widget都应该从InheritedWidget中派生,避免build函数实现代码的嵌套过于复杂(可以更优雅的使用InheritedWidget:provider | Flutter Package (pub.dev))。但是,InheritedWidget的数据共享是单向的,很多时候确实是不便的,在划分多层次时容易被后续的需求变动推翻,但是单向共享数据的设计是合理的(避免双向依赖)。另一方面,我个人认为有时合理的设计不一定是最佳的设计,如果可能,我会在flutter中实现更方便的state访问机制(引入双向依赖)。
  7. 说到底,声明式用户界面的设计不少完美的,因此我们在使用flutter 声明式编程范式的时候,要知其然更要知其所以然,在实践中灵活发挥其强大的威力,规避弥补其缺陷和不足。

DevTools是个web页面,但是用dart写的!

看上去和web的devtool看起来很像,感觉就是chromium里的devtool的后端,不过其本身是用dart实现的,这也体现出flutter对dart的开发效率的自信,这也让我更加坚定好好学习flutter。

Fluttre的设计原则:

如果对Flutter的设计原则深刻理解后,就会对Flutter很多细节的实现和方向的制定找到一定的内在联系: 

最后再聊一下Flutter Engine。

拉下Flutter engine源码后,粗略看了一下,隐隐的觉得,flutter受chromium项目影响很深,甚至怀疑是同一拨人做出来的。

Build System是GN; 在源码里出现了大量的Copyright 20xx The Chromium Authors的版权声明:

Src目录下的gpu目录就是从chomium里copy出来然后删了不用的文件。

对比了一下flutter和chrome的DEPS文件,核心的库基本是一致的,能找到对应关系:

然后上网上查了一下flutter起源:

Flutter 的诞生其实比较有意思,Flutter 诞生于 Chrome 团队的一场内部实验, 谷歌的前端团队在把前端一些“乱七八糟“的规范去掉后,发现在基准测试里性能居然提高了 20 倍,机缘巧合下 Flutter 就这么被立项。

粗略浏览了一下源码,主要关注lib, runtime, shell三个文件夹即可:

想往flutter里加原生扩展,可以直接在DartIsolate::LoadLibraries添加扩展;想修改VM参数,在DartVM::DartVM构造函数实现。Flutter Engine代码组织清晰,可阅读性很高。让人看一眼就有定制一个的Flutter Engine的冲动。

结语

目前我们的桌面客户端使用C++实现了逻辑跨平台,使用QT实现GUI跨平台。接下来,我们正在计划把APP项目使用Dart实现逻辑跨平台,使用Flutter实现GUI跨平台,最终实现课堂业务的一次开发多平台运行目标。

作为Flutter的初学者,上面很多想法不一定成熟,也期待能尽快成长成Flutter老鸟,思考更多关于Flutter的实践。

参考资料:

Dart 概览 | Dart

Flutter architectural overview | Flutter

Flutter 架构概览 ( 中文文档)

Flutter实战(第二版)

带你全面了解 Flutter,它好在哪里?它的坑在哪里? 应该怎么学? - 专栏 - 声网 Agora RTC 开发者社区

Flutter vs Chromium 动画渲染的对比分析 - 知乎 (zhihu.com)

字节跳动为什么选用Flutter:并非跨平台终极之选,但它可能是不一样的未来 - Gityuan博客 | 袁辉辉的技术博客

Roadmap · flutter/flutter Wiki (github.com)

ocornut/imgui: Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies (github.com)

Flutter 新一代图形渲染器 Impeller_阿里巴巴淘系技术团队官网博客的博客-CSDN博客

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

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

相关文章

AI率过高?掌握这些技巧轻松应对论文AIGC检测

告诉大家一个非常残忍的答案,以后所有论文都会被查ai率的。 学术界不仅关注传统的抄袭问题,还增加了一项名为“AIGC检测”的指标。例如知网、维普等平台都能检测论文AI率。 用GPT写论文虽然重复率基本不用担心,但是AI率基本都较高&#xff…

关于科技的总结与思考

文章目录 互联网时代有趣的数字数据驱动大数据的两个特性数据保护互联网免费模式的再探讨平台互联网的意义人工智能伦理的思考语言理性人梅特卡夫定律冲浪的神奇之处AR的恐怖之处叙词表、受控词表和大众分类法六度/十九度的解读知识图谱是真正的仿生智能幂次法则和优先连接现代…

flinksql 回撤流中主键发生变更的影响(group by中的值发生改变)

flinksql 回撤流中,主键发生变更的影响 1 什么是回撤流2 主键变更场景2.2 实践发生3 实践中发现的比较好的的实时数仓架构1 什么是回撤流 这篇文章主要谈论一个场景,简单来说: 首先我们来简单的说一下什么是回撤流,以及回撤流的底层原理,举个例子: 这个说的不是很清晰…

Nginx设置缓存后,访问网页404 问题原因及解决方案(随手记)

目录 问题描述Nginx文件 解决方案查看error_log日志问题原因修改文件并测试Nginx文件测试 总结 问题描述 在Nginx中设置缓存expires后,结果重启nginx,网站访问404了。 Nginx文件 server {listen 80;server_name bird.test.com;location / {root /app/…

本地Django项目切换使用Python虚拟环境

本地Django项目切换使用Python虚拟环境 之前项目开发时,没有使用虚拟环境。导致现在需要上线导出三方模块比较杂乱,于是想着先在本地通过虚拟环境运行起来,之后再导出三方模块(requirements.txt) 首先在Pychram中查看…

QT开源 串口调式工具

都是基础的代码不详细解释,代码比较多福利链接

微前端基于qiankun微前端应用间通信方案实践

【qiankunvue】微前端子应用之间的通信方式总结 ------------------------------------------------------------------补充--------------------------------------------------------- 什么是微前端? 微前端 微前端是一种多个团队通过独立发布功能的方式来共同构…

【云原生 | 60】Docker中通过docker-compose部署kafka集群

🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 🏅阿里云ACE认证高级工程师 🏅阿里云开发者社区专…

如何生成PDF二维码?扫码就能查看文件内容

在现代科技发展的浪潮中,二维码已经成为了信息传递的主要工具之一,被广泛应用在企业办公、产品包装、教育教学等多中场景里,发挥着重要的作用。今天一起来看看究竟如何制作一个PDF文件二维码吧? 扫码后就可以立即查看PDF文件内容…

Virtualbox 安装 ubuntu + qemu

0. 前言 关于 Virualbox 安装虚拟机的优秀文章太多了,笔者主要是着重梳理一些安装小细节,利己利人!! 如果需要保姆式的安装教程,可以查看后续的参考链接。 1. VirtualBox 的安装 直接去官网搜索最近的软件即可&…

【C++】list的使用(上)

🔥个人主页: Forcible Bug Maker 🔥专栏: STL || C 目录 前言🌈关于list🔥默认成员函数构造函数(constructor)析构函数(destructor)赋值运算符重载 &#x1…

一文读懂筛选控件设计

​筛选的作用是缩小展示范围,筛选控件有时会用于“频道切换”。比如内容型或电商产品,用tab切换不同频道,每个频道内有自己的形态。 而到了 B 端产品,如一个 CRM 系统当中,筛选的逻辑比移动端的复杂,有&…

【qt15】windeployqt 安装依赖

debug模式vs可以使用qt插件新建qt文件 D:\Qt15\5.15.2\msvc2019\bin\windeployqt.exe Warning: Cannot find Visual Studio installation directory, VCINSTALLDIR is not set.D:\Qt15\5.15.2\msvc2019\bin\windeployqt.exe .\filecopier.exeWindows PowerShell Copyright (C) …

【成品论文】2024年数学建模国赛B题成品论文分享(点个关注,后续会更新)

您的点赞收藏是我继续更新的最大动力! 一定要点击如下的蓝色字体链接,那是获取资料的入口! 点击链接加入群聊【2024国赛资料合集】:http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kCe9u9pqQeBrMHgupi-R078l9TuU0RwSl&authKeyRjsYS3Piiw…

Flutter开发效率提升1000%,Flutter Quick教程之定义Api(三)

将tab键切换到Response,会出现这么一个界面 这是添加api返回的json数据。比如我们添加一个json数据。 添加完json数据后,右上角有一个删除按钮。要换json数据的话,可以点击清除再重新输入。 这时候,左边的面板上还会显示出 这个的…

代理记账公司的五大问题及其解决方案

代理记账公司是现代企业管理中不可或缺的一部分,它为企业的日常运营提供了专业、高效的服务,随着行业的发展和竞争的加剧,代理记账公司的面临的问题也日益突出,这些问题主要表现在以下几个方面: 业务流程不规范 许多代…

CodeBlocks官方主题颜色更换及方法

文章目录 一、前言二 、用工具导入配置文件2.1 运行 cb_share_config.exe文件2.2 替换文件2.3 设置主题 三、配置主题3.1 步骤13.2 步骤23.3 步骤3 四、设置光标4.1 配置字体4.2 展示 行号 五、设置左边行号区域部分六、设置完后的效果七、下载地址 一、前言 Codeblocks 默认的…

【全开源】同城跑腿系统源码小程序(FastAdmin+ThinkPHP+Uniapp)

让生活更便捷的一站式服务 一款基于FastAdminThinkPHPUniapp开发的同城跑腿小程序,支持帮取、帮送模式,包含用户端、骑手端、运营后台,支持一键接单/抢单, 为跑腿团队提供技术解决方案,无加密源码,可私有化…

.Net 基于.Net8开发的一个Asp.Net Core Webapi后端框架

1.项目结构 该项目是基于.net8开发的Asp.Net Core WebApi后端服务,集成了Efcore,Autofac,Jwt,AutoMapper,Serilog,Quartz,MiniExcel等组件。该框架简单易上手,没有额外的学习成本; 该项目采用了多层结构设计,有利于解耦,包含公共层&#xff0…

AI绘画SD入门教程:ControlNet篇-Canny边缘检测预处理器

大家好,我是向阳 在本篇中,我来讲讲如何使用预处理器和辅助模型,分别都有些什么作用。 💡 这里说明一下当你调用预处理器而辅助模型显示为无的几种原因: 当已载入SD1.5的模型时,CannyXL的辅助模型不会显示…