2021年我接了一个IoT的项目,当时我想着跨平台能省一半时间,毕竟Flutter吹得天花乱坠。 什么120fps,什么自绘引擎,似乎只要写一份代码就能平趟Android和iOS。 那时候我对原生开发有点腻了,就想试试新东西。 于是屁颠屁颠地搭起了Flutter环境,第一感觉就是舒服,Hot Reload是真快,改个UI秒看到效果。 但问题从release构建开始就来了。
第一件事是包体积。我用flutter build apk --release构建了一个最简单的app(就一个按钮加一个http请求),结果APK大小是19.8MB。 我同事用Kotlin写的同样的功能,Android Studio Debug包才5.4MB,Release包只有3.1MB。 这差距太大了。而且我还没加地图呢。 后来需要集成高德地图,加上各种插件后APK直接飙到34.7MB。 用户反馈说一个大版本升级要几十MB流量,有些人直接不升级了,我当时心里就凉了半截。
更让我头疼的是内存管理。Dart的垃圾回收机制跟Java不太一样,它在低内存设备上做GC时会Stop-the-world。 我实测红米Note 9(4GB RAM)上,一个简单的图片列表(Images.network加载100张图),滚动时帧率掉到45fps,偶尔卡顿到38fps。 同样的列表,我原生写了一个版本,帧率稳定在55fps以上。 而且我观察到Flutter的内存占用量比原生高50%左右,同样的数据,原生App占用120MB,Flutter要180MB。 我没有严格做A/B测试,但多次观察都是这个结论。
调试是另一个大坑。虽然Hot Reload很爽,但一旦遇到插件问题,你就得同时看Dart日志、Android的Logcat和Xcode的Console。 有时候一个MethodChannel调用失败,错误信息完全无头绪。 那次我集成蓝牙插件flutter_blue_plus,扫码连接设备时,onCharacteristicChanged回调经常丢失,找了两天。 最后看到GitHub的issue里面说可能是蓝牙缓冲区冲突,推荐改用原生实现,当时真是气得不行。
生态问题就更不用提了。很多插件都是个人维护的,文档不全,而且版本更新跟不上。 我用过一个叫flutter_map的插件,只因为跟SDK版本冲突,导致iOS上地图白屏。 后来我只好用webview加载H5地图,体验差到不行。 还有PlatformView的性能问题,在Android上嵌入原生百度地图的时候,每次拖动地图都会出现白块。 那种感觉就像回到了2015年的WebView。
团队方面,招人也是难事。现在路上随便扔块砖头,砸到十个前端可能有八个会Vue,但你找一个愿意学Dart的几乎没有。 我们后端同事看到这玩意儿更是摇头。 后来项目迭代到1.3版本,我实在顶不住了,花了一个月时间把核心业务用Kotlin重写,iOS那边交给另一个同事(他是搞SwiftUI的)。 重写之后APK回到了6.2MB,内存占用降到了140MB,也再也没有什么白块。
现在回想,我不是说Flutter一无是处,对于纯界面展示、表单收集、内部工具类应用,它确实快。 但是,只要涉及底层硬件交互、复杂动画、低端机适配,或者对包体积有严格要求,原生仍然是那个更靠谱的选择。 网上那些“跨平台一统江湖”的论调,多半是没做过深度集成的人写的。 我不觉得我的经历能代表所有项目,但希望给那些正在犹豫要不要上Flutter的兄弟们一点参考。