This is the first version of Local Native Rust GUI desktop application (iced implementation).
- We finally support Windows!
- macOS release is still in dmg format.
- Appimage build has some issue.
This is the first version of Local Native Rust GUI desktop application (iced implementation).
说起来这是我的公开的第二个Rust项目,第一个还是去年大四上学期和朋友一起做的Bevy游戏项目(我们还有一个项目正在做,但是因为我最近实在是太忙了,所以没有参与进去,感兴趣的可以参与一下:https://github.com/rgripper/village-sim )。我很感谢这两次机会,让我有足够的时间和精力去深入对Rust的学习和了解。这次总结,将会从三个方面来概述。
Local Native的跨平台桌面端使用的是iced来写的,iced很好用,概念抽象的很简单,如果你习惯上了iced的各种抽象,你会感受到Rust作为高级语言来写的快感。同时官方社区也很有爱,有各种问题提了issue或者去官方的群里问,很快就会有回复。
但是现阶段的iced并不完美,仍然有很多缺陷,比如没有动画支持,没有富文本支持,没有官方的多语言支持,以及各种控件太少了,这些都是官方正在竭力去补全的,特别是它还选用了wgpu作为渲染后端,我相信在不远的将来,它会是一个很好的简易跨平台应用解决方案(style还是太难写了,如果有热重载和对style进行重构,iced会更强大)。
而iced使用的语言就是Rust,说到Rust,很想分享一下自己的学习经历。2018年初的时候,我只会python,而且还是超级菜的那种。那个时候听到不少言论,说除了python以外应该再学两门编程语言,一门足够底层,一门足够工业,前者我在知乎被各种帖子的鼓吹后(特别是Rust编程之道的作者,张老师),选择了Rust,后者因为学校的课程中就包含了C#和Java,所以没有特意的去学习。
刚开始接触Rust的时候:“呀,这些概念,好严谨,好透彻,完全能够从Rust里感受到各种设计的因果关系,实在太强了!”(可能是我其他语言接触的太少的原因,只会python的我被Rust深深吸引了)。
随着深入的学习了解,开始着手各种项目练手的时候,被编译器各种教做人:“生命期怎么这么难呀,范型、trait限定的写法好吓人呀,异步状态机的什么鬼,所有权咋这么难用!”这个阶段持续时间有长有短,每一个问题都能单独拿出来说,每次将这些困惑的问题解决掉,消化掉的时候,会从中汲取极大的满足感。我的建议是,多看几家的文档,教程,找出合适的自己的,多和群友交流沟通,一定有让你满意的答案。
现在的阶段,代码写起来很顺畅,编译通过很安心,逐渐的反而会去想为啥这种错误编译器没有报错之类的事了(写这个项目的时候,有用到as
,不少地方出现了溢出的问题,所以如果习惯了被Rust编译器保护,突然来这么一下,感受还是挺奇妙的)。
这次的项目我负责的是整个跨平台的前端开发,同时负责后端依赖更新到最新版本,保证后端功能正常。项目的架构比较常见,是通过json-rpc的方式在前后端进行数据交换,前端的开发在熟悉iced之后,进展还是很快的。整个过程有充足的时间让我学习和了解iced,以及深入Rust,也因此,整个项目实际上是进行了一个较大的重构,重构之后的代码更简洁,性能上也更好了。
重构的过程中找到了比之前更好的实现方法,以及各种更优雅的写法,最熟练的还是对迭代器的使用吧,长时间的各种对迭代器的使用,已经完全被这种方式给套牢了,好用确实是真的好用。
也因为有考虑过上架苹果的AppStore和微软商店,所以做了打包,打包过程比较容易,这得多亏了tauri团队对Rust社区的贡献,再次感谢!
比较麻烦的是和浏览器扩展做初始化吧,几乎有两周的时间在弄这个,虽然这期间有其他事耽误了一下,但因为多个平台的多个浏览器不一致,这部分还是写的比较麻烦的。
另外就是后端同步过程中出现的一些问题,调试也听花时间,知道截止发稿,还有个安卓11同步崩溃的问题没解决,这周有空可以搞一下。
今年我毕业了,同时现在也找到了一份Rust开发的工作,是做substrate开发的。最近正在看文档之类的,多亏了早年被各种Rust英文教程的轰炸,让我现在看substrate文档没多大压力。
我很感谢这次的实习机会,因为如果没有这次的机会的话,我不一定能找到编程相关的工作。我本科是学化工的,做毕设期间老师也劝我找份化工的工作,说去厂里时间很充裕,足够我去研究编程之类的东西,不过最后还是没去,最大的原因还是这份实习吧,我想着如果能把这部分工作做好的话,找份Rust工作,应该还是可以的。
在之前项目快结尾时,我们Local Native团队参加了Dweb社区举办的项目分享活动,也是那个时候认识了现在的leader,经过交流之后加入了团队。团队对我最大的诱惑是leader对开源项目的态度吧,leader很鼓励我平时多参加开源社区,如果不出意外的话,在substarte开发能稳定进行之后,bevy之类项目会再搞起来。
说点牢骚话,此前在群里看到群友发的一句话,说有些人代码出道即屎山。一不小心就把自己带入进去了。抛开我Bevy的项目不谈,那个是和朋友一起写的,那个时候确实很菜,同时当时Bevy真的资料很少,所以这个就不深究了。这次的项目,现在的版本其实重构了一次的,在之前还有个从demo写过来的版本,重构过程很美好,此前的很多写法确实可以用屎山形容,最终呈现出来的代码还算满意,但有些地方还是没有处理好,比如绘制日期过滤器,交互上还可以加强,视觉上也是;比如主题风格,对颜色把握确实不够,还需要再好好调整。最终的教程,就是在这样的情况下写出来的,所以听到这样的话的时候,心里还是蛮愧疚的,不过,这些在未来都会被尽可能的解决,所有的教程及代码,都会维护到iced出1.0版本,至少会有个三到四年时间吧,对教程有各种需要改进的都可以提issue,或者给我发邮件:cupnfish AT icloud.com
关于cupnfish,这是一个很中国的名字,杯多鱼,类似的还可以cup1egg,cup2dog如果以后我真用bevy做自己的游戏项目了,这些就当作隐藏彩蛋吧。
使用iced实现LocalNative的跨平台桌面GUI,大致上要实现electron版本的基本功能,总结如下:
除了以上electron版本已经支持的功能,可能还会支持以下功能:
目前大部分代码已经完成了,还有少部分的todo需要完成或者舍弃,除了上述todo以外,我更想和大家分享在iced
和druid
之间,为什么最后选择了iced
,这部分没有太多涉及到技术层面的东西,更多是对使用体验上的一些考量。
druid
和iced
是Rust社区中较为知名的GUI框架,其中iced
更是以其好用的api从而俘获了大部分开发者的青睐(从Github的star数量上就可见一斑)。二者之间也有一定的关系,在介绍关系之前会大致介绍一下二者是在什么样的情况下被设计出来的。
先谈druid
吧,正如druid
的Github项目主页上Readme所言,目前驱动druid
开发下去的主要动力是runebender,一个字体编辑工具,依托druid
的跨平台能力,该编辑器在不同平台上有着较好的体验。同时如果体验一下这个字体编辑工具,能够感受到druid
足以完成大部分图形界面客户端开发中的难点,也就是说druid
有足够的能力去实现一个跨平台的复杂图形用户界面。目前druid
的渲染后端是piet
,druid
的作者自己有意愿将wgpu
作为druid
的可选后端,但是希望wgpu
能够足以胜任这份工作时才会去做出这种改变。piet
和wgpu
的优缺点在于piet
更轻量,在低性能设备上运行的时候,目前来说体验上是要比wgpu
要好的,wgpu
更像是一个游戏渲染后端,需要gpu有一定的支持,同时由于当前wgpu
对OpenGL的支持并不是很好,从某种角度上来说Wgpu
对老的设备并不是很友好(新版本的wgpu
已经对OpenGL有了初步支持)。
而iced
的初衷就更简单了,作者本身有一个游戏引擎需要用到GUI工具,因此自己手动写了一个,谁想到游戏引擎没火,iced
却火了起来,关于iced
开发上限可以看看Project Showcase,其中较为出名的一定是这个:Cryptowatch Desktop,相对于druid
的渲染后端piet
,iced
则在一开始就选择了wgpu
作为自己的渲染后端,当然iced
自己宣称是渲染器无关的GUI工具,在后续官方确实也添加了对OpenGL的支持(直接通过glutin,一个Rust的OpenGL绑定,而不是通过wgpu
)。
理解了两者开发初衷上的不同之后,你就能够感受到两者对一些理念上有着明显的不同,比如就成熟度而言,druid
比iced
更像是一个完整的GUI方案,你能想到的大部分功能都有了足够的解决方案,虽然有些还在完成中,但是你已经能直接能用到很多简单好用的API了,相对于iced
是一个游戏GUI框架的考量,你能在编译之后的程序体验上,感受到druid
真的像是一个为了各个平台而设计的GUI工具,说的具体点,iced
到目前还没有一个支持各个平台的菜单控件(对,你没看错,居然连菜单控件这种很常用的东西都没有),而durid
已经完全对各个平台有了不同的,完全绑定平台原生的菜单控件,并且 API设计上也十分好用。druid
已经有了一个可用的多语言支持(切换语言还没有实现,不过已经很快就会实现了),而iced
甚至连解决在输入框里打中文,输入法文本悬浮框会飘出应用程序的PR还没有合并。
那说了这么多,全是druid
的优点,那为啥最后还是选择了iced
呢?
因为iced
更简单,这是最重要的,这次SoC的计划除了实现那个GUI之外,其实还有一个更重要的事,就是实现一个项目实践的教程,最为教程的最佳选择,iced
绝对当仁不让,你能从这次项目实践教程中体验到Rust开发如此有趣,在初步掌握了iced
之后,你便能够将你的所有想象力轻易表达出来。
不仅仅是简单这么个有点,在一定程度上由于iced
的渲染后端现在是wgpu
,而druid
是piet
的原因,在一些场景下性能是iced
的最大优势,你会感受到你的App是如此的丝滑(虽然iced
还没有动画支持😀)。同时iced
和异步框架的深度融合,在开发中会让你更为舒适。
总结下来就是以下三点,让我最后选择了iced
,而不是druid
:
iced
更简单iced
渲染后端是wgpu
iced
足够完成当前的需求既然提到了事件处理,我还是要夸一下iced
的,如果你看过iced
的示例代码,会发现在iced
的update逻辑里要求你返回一个Command
枚举,这个Command
你可以将你想要执行的异步操作直接给它调用,就能够得到一个性能还算不错的应用程序。而druid
的这部分代码要怎么处理呢?如果你熟悉并发中channel
的概念,你在使用druid
的事件处理时会理所当然的想到,这不就是channel
么,通过一个类似channel
的形式,将信息传递到一个集中处理该信息的地方,使用起来实在是不太优雅。
在灵活性上,iced
让你写起来完全像是在写elm
(果然不愧是受到elm
启发),而druid
的Lens
概念足够把很多人给劝退了,所以单单是在这些方面,就足以让我为了接下来的教程,而选择iced
,而不是durid
。
好了既然说到教程,就把教程的整体放在这里:
localnative_core
获取GUI需要用到的数据wrap
控件timeline
控件大概的内容就这么多,其中在序这部分会着重讲一下开发环境的搭建,其中最为冗长的是第一部分,实现一个完成的note,这里又需要划分为三个部分来讲,最后一个打包部分只会讲到windows平台的,因为我没有mac,所以mac打包还需要各位自行尝试。大概内容就是这些,更新速度的话,其实代码写到这里,除了第三部分的timeline
控件没写,基本功能都实现了,都是一些小问题需要去解决。
最后,说点我个人的感想吧,这次SoC我个人还是十分珍惜这个机会的,我很喜欢Rust,但是现在的Rust工作环境大概七成是区块链,剩下的三成还有不少是搞分布式、数据库的,所以相对于这些而言,居然有一个GUI开发的Rust实习机会,对我来说实在是太令人高兴了,再加上还是一个开源项目,又着实令人兴奋一把。从接触Rust至今,已经快两年半的时间了,但正是因为Rust十分有趣,坚持到现在已经是一种享受的姿态,这次教程的受众主要还是那些对Rust感兴趣,想要动手写点小工具之类的人,只需要知道语法是在表达什么就够了,所有权生存期这些东西交给编译器去锤炼你吧,希望大家喜欢会喜欢这个系列。
推进 FLOSS 项目 https://localnative.app 的 Rust GUI 代码和相关的 educative 教程的编写, 招募代码, 文档和教程贡献同学。
借鉴G家2021 SoC的时间线
日期 | 事件 | 津贴 |
---|---|---|
March 29 - April 13 | 申请 | |
April 13 - May 17 | 确定申请结果 | |
May 17 - June 7 | 熟悉代码和框架,写计划 Blog | |
June 7 - July 18 | code() and debug() and document() | July 18 First Evaluation 45% |
July 18 - August 16 | code() and debug() and document() | |
August 16-31 | 写总结 Blog 和 educative 教程文档 | August 31 Final Evaluation 55% |
欢迎有Rust经验的同学申请!
备注 SoC 发送