Flutter入门:从零开始构建跨平台应用

MySQL修理工
2025-12-15 08:38
阅读 581

上周五晚上11点,我还在公司对着一堆Docker日志抓狂——没错,就是那个双11压测后线上突然502的锅。作为网易成都这边一个干了三年服务端的老油条,日常写Springboot接口、调优Redis缓存、和运维“友好”对线已经成了生活的一部分。但最近被拉进一个新项目组,领导丢给我一句:“你们服务端也得懂点前端,这次我们试试用Flutter搞个内部工具App。”

我?写UI?不是,我连CSS都写不利索啊!不过转念一想,反正最近在学Rust(成都这节奏太舒服了,下班还能卷点新东西),顺手搞搞Flutter也行,说不定哪天跳槽能吹“全栈”(狗头保命)。

为啥是Flutter?

其实一开始PM(产品经理)嚷嚷着要上React Native,说社区大、生态好。但我们组后端全是Java系的,Springboot写了三年,对JS那一套真有点PTSD。而且之前有个兄弟用RN写了个活动页,结果iOS审核被拒三次,理由是“动态下发代码”,直接把人整emo了。

Flutter不一样——Dart语言虽然小众,但语法对Java/C++出身的人极其友好,而且编译成原生ARM代码,性能稳如老狗。更重要的是,一套代码跑iOS/Android/Web甚至桌面端,对于我们这种人手紧张、又要快速交付的内部工具项目,简直是救命稻草。

吐槽一句:我们测试同学听说不用同时测两套UI,当场请我喝了杯霸王茶姬。感动!

环境搭建:别被VSCode插件劝退

我平时写代码全靠VSCode + 一堆插件续命。Flutter官方推荐用Android Studio,但我试了下,启动慢得像加载《逆水寒》的登录界面。果断切回VSCode,装上这几个插件:

  • Flutter
  • Dart
  • Pubspec Assist(自动生成依赖引用,懒人必备)
  • Error Lens(报错直接标红,比看终端快十倍)

然后终端里跑:

flutter doctor

第一次跑大概率一堆❌,尤其是iOS开发者证书那块。别慌,按提示一步步来就行。我在Mac上折腾了半小时Xcode命令行工具,Windows同事更惨,直接重装了两次Git for Windows(记得选“Use Git from Windows Command Prompt”)。

小贴士:如果你也在成都,建议找个周末去太古里星巴克边喝咖啡边配环境——反正不花钱,纯属玄学加速。

从“Hello World”到连上Springboot后端

新建项目贼简单:

flutter create my_internal_tool
cd my_internal_tool
flutter run

默认会弹出一个计数器页面。但我们要的是连后端API!刚好我们Springboot服务有一套现成的RESTful接口,比如获取用户列表:

GET /api/v1/users

在Flutter里发起HTTP请求,得先加依赖。打开pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.5  # 别用dio!新手容易被拦截器绕晕

然后写个简单的Service类:

import 'package:http/http.dart' as http;
import 'dart:convert';

class UserService {
  static Future<List<dynamic>> getUsers() async {
    final response = await http.get(
      Uri.parse('http://your-springboot-server:8080/api/v1/users'),
    );
    
    if (response.statusCode == 200) {
      return jsonDecode(response.body);
    } else {
      throw Exception('Failed to load users');
    }
  }
}

重点来了:如果你在模拟器里跑,地址千万别写localhost!Android模拟器里要用10.0.2.2,iOS模拟器才认localhost。我们组新人在这栽过两次,差点被运维笑死。

踩坑实录:状态管理与平台差异

坑1:StatefulWidget 写到怀疑人生

刚开始我把所有逻辑塞进一个Widget里,结果setState一刷新,整个页面重绘,输入框内容全丢。后来才明白:Flutter的状态管理不能乱来

对于小项目,用Provider就够了(比Bloc简单多了)。先装依赖:

provider: ^6.0.5

然后把UserService包装成ChangeNotifier,UI层用Consumer监听。这样数据变了,只刷新相关组件,再也不用担心输入框“瞬移”。

坟2:iOS和Android的UI表现不一致

比如一个按钮,在Android上圆角正常,iOS上却方得像砖头。查文档才发现:Material Design 和 Cupertino 风格有差异

解决方案很简单——别混用!如果目标用户主要是Android(我们内部工具确实如此),就全用MaterialApp + ElevatedButton;如果是iOS优先,就上CupertinoApp

另外,字体大小也要注意。我们设计师给的Figma稿是14px,但在Flutter里写fontSize: 14,iOS显示会偏小。最后统一用MediaQuery动态计算:

Text(
  'Hello',
  style: TextStyle(
    fontSize: MediaQuery.of(context).textScaleFactor * 14,
  ),
)

坑3:Release包打出来白屏?

这个问题卡了我整整一天。Debug模式一切正常,一打release包就白屏。最后发现是网络权限没开

  • Android要在AndroidManifest.xml加:
    <uses-permission android:name="android.permission.INTERNET" />
    
  • iOS要在Info.plist加:
    <key>NSAppTransportSecurity</key>
    <dict>
      <key>NSAllowsArbitraryLoads</key>
      <true/>
    </dict>
    

血泪教训:永远先检查权限,再骂框架!

性能优化:别让用户觉得“卡”

虽然Flutter号称60fps,但如果滥用ListView.builder或者图片不压缩,照样卡成PPT。

我们做了三件事:

  1. 图片用cached_network_image:自动缓存+占位图,避免滚动时闪白
  2. 长列表用ListView.builder:只渲染可见项
  3. 复杂动画用RepaintBoundary:隔离重绘区域

上线后用Flutter DevTools测了下,帧率稳定在58-60fps,测试同学终于没提“卡顿”bug了(感动哭)。

发布到应用市场?其实没那么难

内部工具不需要上架,但好奇还是试了下。

  • Android:生成签名APK,一行命令搞定
    flutter build apk --release
    
  • iOS:得用Xcode Archive,但Flutter帮我们处理了90%的配置。唯一麻烦的是证书,建议用Apple Developer账号自动管理。

最骚的是,同一套代码,还能编译成Web版!虽然性能不如原生,但给运营同学临时查数据够用了。

总结:值得投入吗?

从抗拒到真香,我只用了两周。现在这个内部工具已经替代了三个老旧的H5页面,运维也不用半夜爬起来修Nginx配置了(他们请我吃了顿火锅,成都的快乐就是这么朴实无华)。

对比项 原H5方案 Flutter方案
开发效率 需适配多端 一套代码全平台
性能 受限于WebView 接近原生
调试体验 F12看控制台 DevTools可视化
与Springboot对接 CORS各种坑 直接HTTP调用

当然,Flutter也不是银弹。如果你要做大量原生交互(比如蓝牙、传感器),还是得写Platform Channel,那感觉就像在Java和Dart之间“传纸条”,挺痛苦的。

但对我这种服务端出身、偶尔客串移动端的“缝合怪”来说,Flutter真的是性价比之王。下次团建,我准备跟PM提议:咱们新活动页也用Flutter吧?省下的加班时间,够打三把《永劫无间》了。


后记:写完这篇教程,我发现隔壁组做Unity的哥们也开始偷看Flutter文档了。果然,在成都,没有一个程序员能拒绝“少加班+多摸鱼”的技术方案(手动狗头)。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝