Sucha's Blog ~ Archive for October, 2025

25年10月19日 周日 22:54

Flutter(1)

各种原因,换了一家公司,原来那家创业公司8月底老板突然内部会议上说发不出下个月工资了(-_-),我就火速离职了,毕竟 App 当时也做的差不多了,我也没法举债上班,毕竟没股份。

也不知道新公司怎么看得上我,因为我之前没有 Flutter 的经验,只有 Swift + ObjC 的经验,ObjC 和 Swift 都用过连续 4+ 年左右,总的 iOS 也有 10+ 年 的经验了。

我第一周是从 dart 语言看起的,看得头大,第一周收获不大,老板可不会等你那么久,于是第二周是直接上手做页面了,其实 dart 语言只懂皮毛,开了 4 个 AI 页面,东问西问,之所以要开那么多,是因为有些问题需要缓存着,同一个问题需要从不同细节问,毕竟一个细节,就能卡住我好久。

同事的 Flutter 经验很足,而且搭建了页面框架,所以我只是画几个 widget,以及链接一下数据,搞一下 ListView 就把第一个页面做好了,看起来也还行。再说当时产品催了一下 UI 了吧,给的我是详细设计稿,所以我可闲不下来。

其实这周开始是有点困难的,因为一开始想着不如先搞个导航模块,当时对 Flutter 还不熟悉,就开始吭呲吭呲地搞,我之前用 Swift,习惯了导航模式带参数,用的 enum,比如

enum ModuleExamplNav {
    case pageIndex(param Int, param String)
}

类似这样,但是 dart 语言的 enum 只能带同一个类型的参数,与 swift 差异很大,如果用 @freezed 库是可以的,但是后面还遇到了 build_runner 生成的映射文件居然编译通不过的问题,这就相当坑了;还有同事调研了一下 freezed,觉得目前项目并不很需要这个依赖库,并未打算采用,那这条路估计就断了。

还有 iOS 的导航,基本上是页面的 push、pop、present、dismiss,也就是 navigation controller 在哪一个层级的问题,有多少级的 navigation controller,比如 tab controller 第一级就是 navigation controller,之后 present 了一个页面,为了 present 之后还能继续 push,其实 present 的是一个 navigation controller,其内容才是 present 展示的。

navigation controller 包含了页面栈的层级,本来就包含了需要展示的内容,只是动画过程中,layer 分成了 model layer、presenter layer、以及 render layer(这个我没用过,查了一下是私有的,知道概念就行),前两者我们是能够代码操作的,只是时机不同。

但是在 flutter 中,所有展示相关的都是 widget,虽然他们功能大不相同,以及不一定在最终展示上显示,只是在逻辑概念上、layout 上需要用到,毕竟 Flutter 是描述性的 UI,类似 SwiftUI。

先说导航,对比 iOS 导航,flutter 的导航分成两部分,一部分是 Navigator,用到的比如 Navigator.of(context) 就是它,是管理页面层级的,另外一部分,是 push 的内容,包含 PageRoute,比如 MaterialPageRoute,是管理转场动画的,然后对比 push、pop、present、dismiss 其实都还好理解,但是有时候,如果需要 present 后再 push 盖住 present,其实是用之前页面的 context 来做的,目前我还不知道有没有其他的方案,这个造成 pop 到某一个页面的过程中,貌似需要用到一些技巧,但不确定是好的解法,毕竟我的 flutter 经验还不足。

还有就是页面具体细节相关的了,先是 layout,Expanded 的 parent 必须是 row、column 之类的,然后如果 layout 过程中,某些 widget 需要用到 parent 的宽高,不像 UIKit 中,在 layoutSubviews 里面操作就行了,即便是 build context 也没有带下来信息,毕竟 build context 的时候,widget 并未挂接到渲染树上,此时需要用 LayoutBuilder,所以在 build 里面 LayoutBuilder 虽然占用了了一个缩进,但是只是为了拿一个 parent widget 的宽高之类的。

同样的还有 align、padding,所以我搞了一个 extention WidgetExt on Widget,用来放链式配置,有些不重要的 layout,没必要占用一个缩进。

工作的第一个页面,还涉及到了 gestue,flutter 的 gesture 还好,相对 iOS 是挺好理解的,但是也跟 iOS 有一些平台特殊的逻辑,比如 iOS 的 attributedString,参数就有 link 的,flutter 这边则使用 RichText,带的 TextSpan 就有 recognizer 参数,但是呢,如果 TextSpan 有 children 带了一堆 TextSpan,那不好意思,这个容器类似的 TextSpan recognizer 就接收不到响应了,都被其 children 响应了,即便我在 children 的 TextSpan 没有一个填了 recognizer。

还有居然区分了 StatelessWidget StatefullWidget,这个我还不是很理解,虽然也有用 State 搞了几个,以及页面状态管理用的是 riverpod,用 WidgetRef 来 watch、read 和 write 数据并更新页面。

之前是习惯了 RxSwift 或者 Combine,现在又刷新了,前端 3 年一小变、5 年一大变,哭。。。

25年10月19日 周日 20:31

喀什六天行

有空再写吧,这里留个引子。。。