去年我用 Flutter 做了个专注番茄 APP一套代码同时支持 Android 和 iOS。今天分享完整开发过程包括踩过的坑。一、为什么选 Flutter做之前对比了几个方案最后选 Flutter因为一套代码AndroidiOS 同时上线Dart 语言像 Java有 Java 基础 2 天就能上手热重载开发快改代码秒看效果二、环境搭建我的环境Windows 11Android StudioFlutter 3.19安装步骤# 1. 下载 Flutter SDK git clone https://github.com/flutter/flutter.git -b stable # 2. 配置环境变量 # 把 flutter/bin 加到 PATH # 3. 检查环境 flutter doctor踩坑第一次运行 flutter doctor 提示 Android SDK 找不到需要手动指定路径。三、项目结构focus_tomato/ ├── lib/ │ ├── main.dart # 入口 │ ├── screens/ │ │ └── home_screen.dart # 主页面 │ ├── models/ │ │ └── timer_model.dart # 数据模型 │ ├── providers/ │ │ └── timer_provider.dart # 状态管理 │ └── utils/ │ └── storage.dart # 本地存储 ├── pubspec.yaml # 依赖 └── android/ / ios/ # 平台配置四、核心代码数据模型timer_model.dartclass TimerModel { int duration; // 专注时长秒 int remaining; // 剩余时间 bool isRunning; // 是否运行中 bool isBreak; // 是否休息中 TimerModel({ this.duration 25 * 60, // 默认25分钟 this.remaining 25 * 60, this.isRunning false, this.isBreak false, }); // 格式化显示 25\:00 String get displayTime { int minutes remaining ~/ 60; int seconds remaining % 60; return ${minutes.toString().padLeft(2, 0)}:${seconds.toString().padLeft(2, 0)}; } }状态管理timer_provider.dartimport dart:async; import package:flutter/foundation.dart; class TimerProvider extends ChangeNotifier { TimerModel _timer TimerModel(); Timer? _countdownTimer; TimerModel get timer _timer; // 开始计时 void start() { if (_timer.isRunning) return; _timer.isRunning true; notifyListeners(); _countdownTimer Timer.periodic(Duration(seconds: 1), (timer) { if (_timer.remaining 0) { _timer.remaining--; notifyListeners(); } else { // 时间到 complete(); } }); } // 暂停 void pause() { _timer.isRunning false; _countdownTimer?.cancel(); notifyListeners(); } // 重置 void reset() { _timer.isRunning false; _timer.remaining _timer.duration; _countdownTimer?.cancel(); notifyListeners(); } // 完成 void complete() { _timer.isRunning false; _countdownTimer?.cancel(); // 切换休息/专注 _timer.isBreak !_timer.isBreak; _timer.duration _timer.isBreak ? 5 * 60 : 25 * 60; // 休息5分钟专注25分钟 _timer.remaining _timer.duration; notifyListeners(); } override void dispose() { _countdownTimer?.cancel(); super.dispose(); } }主页面home_screen.dartimport package:flutter/material.dart; import package:provider/provider.dart; import ../providers/timer_provider.dart; class HomeScreen extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xFF1A1A2E), // 深蓝背景 body: Center( child: ConsumerTimerProvider( builder: (context, provider, child) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 状态标签 Text( provider.timer.isBreak ? 休息时间 : 专注时间, style: TextStyle( color: Colors.white70, fontSize: 18, ), ), SizedBox(height: 20), // 倒计时显示 Text( provider.timer.displayTime, style: TextStyle( color: Colors.white, fontSize: 80, fontWeight: FontWeight.bold, fontFamily: monospace, ), ), SizedBox(height: 40), // 控制按钮 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _buildButton( icon: provider.timer.isRunning ? Icons.pause : Icons.play_arrow, onPressed: () { if (provider.timer.isRunning) { provider.pause(); } else { provider.start(); } }, ), SizedBox(width: 20), _buildButton( icon: Icons.refresh, onPressed: () provider.reset(), ), ], ), ], ); }, ), ), ); } Widget _buildButton({required IconData icon, required VoidCallback onPressed}) { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF16213E), foregroundColor: Colors.white, padding: EdgeInsets.all(20), shape: CircleBorder(), ), child: Icon(icon, size: 32), ); } }入口文件main.dartimport package:flutter/material.dart; import package:provider/provider.dart; import providers/timer_provider.dart; import screens/home_screen.dart; void main() { runApp(FocusTomatoApp()); } class FocusTomatoApp extends StatelessWidget { override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) TimerProvider(), child: MaterialApp( title: 专注番茄, debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, scaffoldBackgroundColor: Color(0xFF1A1A2E), ), home: HomeScreen(), ), ); } }依赖配置pubspec.yamlname: focus_tomato description: 专注番茄钟APP publish_to: none version: 1.0.01 environment: sdk: 3.0.0 4.0.0 dependencies: flutter: sdk: flutter provider: ^6.1.1 shared_preferences: ^2.2.2 # 本地存储 dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^3.0.1 flutter: uses-material-design: true五、踩坑记录坑1Timer 内存泄漏刚开始没取消 Timer退出页面后还在后台跑。解决在 dispose() 里 cancel()。坑2状态不更新修改数据后页面没变化。解决必须用 notifyListeners()。坑3iOS 打包失败第一次打 iOS 包提示证书问题。解决需要 Apple Developer 账号配置证书。六、效果展示界面很简单深蓝背景大号倒计时播放/暂停/重置按钮专注25分钟 → 休息5分钟 → 循环七、打包发布# Android flutter build apk --release # iOS需要 Mac flutter build ios --releaseAPK 大小15MB 左右。八、总结用 Flutter 做番茄钟2 天完成 MVP1 周上线双平台。核心就 3 个文件200 行代码搞定。如果你也想做跨平台 APPFlutter 是个不错的选择。