示例一:金融理财 App(Flutter)
项目名称
XX 互联网金融 App(Flutter)
项目背景
公司原有 iOS 和 Android 两套原生代码,开发成本高,功能迭代慢。金融业务对性能和安全要求高,需要高性能的跨端方案。选择 Flutter 实现 60fps 流畅体验。
业务场景
- 行情中心:实时 K 线图、分时图、大盘指数
- 基金交易:买入、卖出、定投设置
- 资产总览:收益曲线、持仓明细
- 理财产品:产品列表、详情、购买
- 资讯动态:财经新闻、公告通知
核心职责
1. 离线缓存 - 行情数据
业务场景: 用户频繁查看基金净值、股票行情,每次刷新都请求服务器
问题
- 行情接口 QPS 高,服务器压力大
- 用户流量消耗大,每天产生大量重复请求
- 弱网环境下行情刷新失败
解决方案
- 使用 Hive 本地数据库缓存行情数据
- 基金净值缓存 30 分钟,K 线数据缓存 5 分钟
- 实时数据通过 WebSocket 推送,历史数据走缓存
- 离线时展示最近一次缓存数据
技术实现
// 缓存层
class MarketCache {
final box = Hive.box('market');
Future<MarketData?> get(String code) async {
final cached = box.get(code);
if (cached == null) return null;
// 检查过期
if (DateTime.now().difference(cached.timestamp) > Duration(minutes: 30)) {
return null;
}
return cached;
}
Future<void> set(String code, MarketData data) async {
await box.put(code, data);
}
}
// 业务层
Future<MarketData> getMarket(String code) async {
// 先读缓存
final cached = await marketCache.get(code);
if (cached != null) return cached;
// 请求接口
final data = await api.getMarket(code);
await marketCache.set(code, data);
return data;
}
项目成果
- 行情接口 QPS 从 5000 降到 1200,降低 76%
- 用户流量消耗减少 60%
- 行情加载成功率从 90% 提升到 99%
2. 启动优化 - 金融级性能
业务场景: 用户打开 App 查看实时行情,要求启动快、响应快
问题
- 冷启动需要 3 秒,用户感觉慢
- 首页渲染卡顿,影响体验
- 大盘数据加载慢,用户焦虑
解决方案
- Splash 页面优化,使用 Flutter native splash
- 首页骨架屏,先展示框架再填充数据
- 数据预加载,并行请求自选股、大盘指数、资讯
- 图表懒加载,滚动到可视区域再渲染
- 使用 Isolate 处理复杂计算,避免阻塞 UI
技术实现
// 预加载关键数据
@override
void initState() {
super.initState();
_loadCriticalData();
// 延迟加载非关键数据
Future.delayed(Duration(seconds: 1), () {
_loadNonCriticalData();
});
}
Future<void> _loadCriticalData() async {
await Future.wait([
_loadUserAsset(), // 用户资产
_loadMarketIndex(), // 大盘指数
_loadSelfSelect(), // 自选股
]);
setState(() => _loading = false);
}
// 复杂计算放到 Isolate
Future<ChartData> _calculateChart(List<Kline> data) async {
return compute(_chartCalculation, data);
}
static ChartData _chartCalculation(List<Kline> data) {
// 大量计算逻辑
return result;
}
项目成果
- 冷启动从 3 秒优化到 0.8 秒
- 首页渲染 60fps 无卡顿
- K 线图滑动流畅度提升 80%
3. 本地数据库 - 交易记录
业务场景: 用户需要查询历史交易记录、持仓变化
问题
- 交易记录接口慢,需要 2-3 秒
- 用户频繁查询,产生大量重复请求
- 离线时无法查看历史记录
解决方案
- 使用 sqflite 存储交易记录
- 首次加载后本地缓存,增量同步新数据
- 支持本地筛选、排序、分页
- 离线可查看所有历史记录
技术实现
class TransactionDB {
Database? _db;
Future<void> init() async {
_db = await openDatabase(
'transaction.db',
version: 1,
onCreate: (db, version) {
return db.execute(
'CREATE TABLE transactions(id TEXT PRIMARY KEY, time INTEGER, amount REAL, type TEXT)'
);
},
);
}
Future<void> saveTransactions(List<Transaction> list) async {
final batch = _db!.batch();
for (var item in list) {
batch.insert('transactions', item.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace
);
}
await batch.commit();
}
Future<List<Transaction>> query({String? type, int? limit}) async {
final List<Map<String, dynamic>> maps = await _db!.query(
'transactions',
where: type != null ? 'type = ?' : null,
whereArgs: type != null ? [type] : null,
orderBy: 'time DESC',
limit: limit,
);
return maps.map((m) => Transaction.fromMap(m)).toList();
}
}
项目成果
- 交易记录查询时间从 2.5 秒降到 100ms
- 支持离线查看 5 年历史记录
- 接口请求量减少 80%
4. Native 能力封装 - 生物识别
业务场景: 登录、支付需要指纹、面容识别
问题
- iOS 和 Android 生物识别接口不同
- 不同设备支持的认证方式不一样
- 需要处理各种异常情况
解决方案
- 使用 local_auth 插件统一接口
- 检测设备支持的认证方式
- 完善的错误处理和降级方案
- 支持密码备用方案
技术实现
class BiometricAuth {
final LocalAuthentication auth = LocalAuthentication();
Future<bool> canAuth() async {
try {
return await auth.canCheckBiometrics && await auth.isDeviceSupported();
} catch (e) {
return false;
}
}
Future<List<BiometricType>> getAvailableBiometrics() async {
try {
return await auth.getAvailableBiometrics();
} catch (e) {
return [];
}
}
Future<bool> authenticate() async {
try {
return await auth.authenticate(
localizedReason: '请验证身份以继续',
options: const AuthenticationOptions(
stickyAuth: true,
biometricOnly: true,
),
);
} on PlatformException catch (e) {
if (e.code == 'NotAvailable') {
// 生物识别不可用,降级到密码
return _authenticateWithPassword();
}
return false;
}
}
Future<bool> _authenticateWithPassword() async {
// 密码验证逻辑
}
}
项目成果
- 支持指纹、面容、虹膜识别
- 登录成功率 99.5%
- 用户体验评分从 4.2 提升到 4.7
5. 异常监控 - 交易异常
业务场景: 用户反馈买入失败、支付卡住等问题
问题
- 交易链路长,不知道哪个环节出错
- 无法复现用户问题
- 金融业务容错率低
解决方案
- 接入 Sentry,捕获所有异常
- 交易流程全埋点,记录每个步骤
- 实时告警,交易失败立即通知
- 建立交易监控大盘
技术实现
// 初始化 Sentry
await SentryFlutter.init(
(options) {
options.dsn = 'https://xxx@sentry.io/xxx';
options.tracesSampleRate = 1.0;
},
appRunner: () => runApp(MyApp()),
);
// 捕获交易异常
Future<void> buyFund(String code, double amount) async {
final transaction = Sentry.startTransaction('buy_fund', 'transaction');
try {
// 步骤1: 风险检查
final span1 = transaction.startChild('risk_check');
await riskCheck(code, amount);
span1.finish();
// 步骤2: 创建订单
final span2 = transaction.startChild('create_order');
final order = await createOrder(code, amount);
span2.finish();
// 步骤3: 支付
final span3 = transaction.startChild('payment');
await payment(order.id);
span3.finish();
transaction.status = SpanStatus.ok();
} catch (e, stackTrace) {
transaction.status = SpanStatus.internalError();
Sentry.captureException(e, stackTrace: stackTrace);
rethrow;
} finally {
transaction.finish();
}
}
项目成果
- 交易异常定位时间从 2 小时缩短到 10 分钟
- 发现并修复 15+ 个交易链路问题
- 交易成功率从 96% 提升到 99.8%
6. 热更新 - 代码推送
业务场景: 发现交易 bug,需要紧急修复
问题
- Flutter 是 AOT 编译,不能像 JS 那样热更新
- 应用商店审核需要 3-5 天
- 影响用户交易体验
解决方案
- 轻量级 bug:通过服务端开关控制功能开关
- 中度 bug:使用 shorebird 进行代码推送
- 重大问题:紧急发版 + 加急审核
技术实现
// 远程配置控制
class RemoteConfig {
static bool get enableNewFeature {
return _config.getBool('enable_new_feature', defaultValue: true);
}
static int get maxBuyAmount {
return _config.getInt('max_buy_amount', defaultValue: 100000);
}
}
// 使用
if (RemoteConfig.enableNewFeature) {
// 新功能逻辑
} else {
// 旧逻辑
}
// shorebird 更新检查
void _checkUpdate() async {
final updater = Updater();
final status = await updater.checkForUpdate();
if (status.isUpdateAvailable) {
await updater.update();
}
}
项目成果
- 紧急修复时间从 5 天缩短到 4 小时
- 功能灰度发布,降低风险
- 避免 3 次重大业务损失
技术栈
Flutter、Dart、Provider、Dio、Hive、sqflite、Sentry
项目成果
- 支持 iOS 和 Android,代码复用率 92%
- App 性能达到原生级别,60fps 流畅体验
- 包体积比原生减少 30%(Android 15MB,iOS 25MB)
- 开发效率提升 50%,双端同步迭代
- 日活 120 万,交易额 50 亿+/月
- 线上崩溃率 0.1%,行业领先
示例二:社交 App(Flutter)
项目名称
XX 即时通讯社交 App(Flutter)
项目背景
打造一款主打年轻人的社交 App,需要流畅的动画、实时的消息推送、丰富的交互。选择 Flutter 实现高性能 UI 和跨平台开发。
业务场景
- 消息聊天:单聊、群聊、语音通话、视频通话
- 动态广场:发布动态、图片/视频、点赞评论
- 个人主页:个人信息、动态列表、相册
- 发现:推荐用户、热门话题、附近的人
- 直播:直播间、礼物打赏、实时互动
核心职责
1. 离线缓存 - 聊天记录
业务场景: 用户需要查看历史聊天记录,包括文字、图片、语音
问题
- 聊天记录存储在服务器,查询慢
- 用户频繁翻看历史消息
- 离线时无法查看聊天记录
解决方案
- 使用 isar 本地数据库存储聊天记录
- 消息收发时自动保存到本地
- 支持全文搜索、按时间筛选
- 媒体文件本地缓存,路径存数据库
技术实现
@collection
class Message {
Id id = Isar.autoIncrement;
late String messageId;
late String conversationId;
late String content;
late int timestamp;
late String type; // text/image/voice/video
late String? mediaPath;
@Index()
late String senderId;
}
class MessageDB {
late Isar isar;
Future<void> init() async {
isar = await Isar.open([MessageSchema]);
}
Future<void> saveMessage(Message msg) async {
await isar.writeTxn(() async {
await isar.messages.put(msg);
});
}
Future<List<Message>> getMessages(String conversationId, {int limit = 20}) async {
return await isar.messages
.filter()
.conversationIdEqualTo(conversationId)
.sortByTimestampDesc()
.limit(limit)
.findAll();
}
Future<List<Message>> searchMessages(String keyword) async {
return await isar.messages
.filter()
.contentContains(keyword)
.findAll();
}
}
项目成果
- 聊天记录加载时间从 1.5 秒降到 50ms
- 支持离线查看所有历史消息
- 全文搜索响应时间 100ms 以内
2. 启动优化 - 消息推送
业务场景: 用户收到消息推送,点击通知进入 App
问题
- 从通知栏启动 App 慢,用户体验差
- 需要快速进入对应的聊天界面
- 未读消息数加载慢
解决方案
- 优化 App 启动流程,减少初始化时间
- 预加载消息列表,并行加载未读数
- 使用 Deeplink 直达指定页面
- 通知数据本地缓存
技术实现
// 启动优化
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 必要的初始化
await MessageDB.instance.init();
await PushService.init();
runApp(MyApp());
// 延迟初始化
WidgetsBinding.instance.addPostFrameCallback((_) {
_initNonCritical();
});
}
void _initNonCritical() {
// 分享SDK
ShareSDK.init();
// 统计SDK
Analytics.init();
}
// Deeplink 处理
void _handleDeeplink(String link) {
final uri = Uri.parse(link);
if (uri.path == '/chat') {
final conversationId = uri.queryParameters['id'];
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ChatPage(conversationId: conversationId)
),
);
}
}
项目成果
- 启动时间从 2.5 秒优化到 0.6 秒
- 通知到聊天页面 1 秒内完成
- 消息推送点击率提升 35%
3. 媒体缓存 - 图片视频
业务场景: 聊天中的图片、视频、语音需要加载
问题
- 媒体文件重复下载,浪费流量
- 加载慢,用户体验差
- 占用存储空间过大
解决方案
- 使用 cached_network_image 缓存图片
- 视频使用 LRU 缓存策略
- 定期清理过期缓存
- 支持用户手动清理
技术实现
// 图片缓存
CachedNetworkImage(
imageUrl: imageUrl,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
cacheManager: CacheManager(
Config(
'chat_images',
stalePeriod: Duration(days: 7),
maxNrOfCacheObjects: 1000,
),
),
)
// 视频缓存
class VideoCache {
final cache = <String, File>{};
final maxSize = 100; // 最多缓存100个视频
Future<File?> get(String url) async {
if (cache.containsKey(url)) {
return cache[url];
}
final file = await _downloadVideo(url);
if (file != null) {
_add(url, file);
}
return file;
}
void _add(String url, File file) {
if (cache.length >= maxSize) {
final firstKey = cache.keys.first;
cache[firstKey]?.deleteSync();
cache.remove(firstKey);
}
cache[url] = file;
}
}
项目成果
- 图片加载速度提升 80%
- 流量消耗减少 65%
- 用户平均停留时长增加 40%
4. MethodChannel - 音视频通话
业务场景: 语音通话、视频通话
问题
- Flutter 没有成熟的音视频方案
- 需要集成腾讯云 TRTC SDK
- iOS 和 Android 原生 SDK 不同
解决方案
- 封装 MethodChannel 调用原生 SDK
- 统一 Dart 层 API
- 处理权限申请、网络切换等
- 完善的错误处理
技术实现
class RTCChannel {
static const platform = MethodChannel('com.xxx.app/rtc');
Future<void> startCall(String userId, bool isVideo) async {
try {
await platform.invokeMethod('startCall', {
'userId': userId,
'isVideo': isVideo,
});
} on PlatformException catch (e) {
throw RTCException(e.message);
}
}
Future<void> endCall() async {
await platform.invokeMethod('endCall');
}
void setCallListener(Function(CallEvent) callback) {
platform.setMethodCallHandler((call) async {
switch (call.method) {
case 'onUserJoined':
callback(CallEvent.userJoined);
break;
case 'onUserLeft':
callback(CallEvent.userLeft);
break;
case 'onCallEnd':
callback(CallEvent.callEnd);
break;
}
});
}
}
项目成果
- 支持 1v1 音视频通话
- 通话成功率 98%
- 通话延迟 < 300ms
5. 性能监控 - 列表滑动
业务场景: 动态列表、消息列表需要流畅滑动
问题
- 列表滑动卡顿,帧率下降
- 不知道哪里影响性能
- 优化缺少数据支持
解决方案
- 使用 Flutter DevTools 性能分析
- 监控帧率,记录卡顿情况
- Isolate 处理数据解析
- 优化 widget 构建
技术实现
// 性能监控
class PerformanceMonitor {
final _frameTimes = <Duration>[];
void startMonitor() {
WidgetsBinding.instance.addTimingsCallback((timings) {
for (final timing in timings) {
final frameDuration = timing.totalSpan;
_frameTimes.add(frameDuration);
// 超过 16ms 认为卡顿
if (frameDuration.inMilliseconds > 16) {
_reportJank(frameDuration);
}
}
});
}
void _reportJank(Duration duration) {
// 上报卡顿数据
Analytics.track('frame_jank', {
'duration': duration.inMilliseconds,
'page': _currentPage,
});
}
}
// Isolate 处理数据
Future<List<Post>> _parsePostsInIsolate(String json) async {
return compute(_parsePosts, json);
}
static List<Post> _parsePosts(String json) {
final list = jsonDecode(json) as List;
return list.map((e) => Post.fromJson(e)).toList();
}
项目成果
- 列表滑动保持 60fps
- 卡顿率从 15% 降到 2%
- 发现并优化 10+ 个性能瓶颈
技术栈
Flutter、Dart、Riverpod、Dio、isar、MethodChannel
项目成果
- 日活 300 万,月活 1200 万
- 平均停留时长 45 分钟
- 消息发送成功率 99.9%
- App 崩溃率 0.08%
- 用户留存率 70%(次日留存)
面试话术(Flutter 项目)
开场(30 秒)
"我做的是一个金融理财 App,用的是 Flutter。选择 Flutter 主要是因为金融业务对性能要求高,Flutter 能达到 60fps 的原生级体验,而且可以一套代码编译到 iOS 和 Android。"
亮点展开
如果问为什么选 Flutter: "我们对比过 React Native 和 uni-app。RN 的性能不够好,复杂列表会卡顿。uni-app 虽然开发快,但动画和交互效果达不到我们的要求。Flutter 是自绘引擎,性能接近原生,而且 UI 一致性好,不用担心双端适配问题。"
如果问技术难点: "最难的是和原生 SDK 集成。我们的音视频通话用的是腾讯云 TRTC,这个 SDK 没有 Flutter 版本。我通过 MethodChannel 封装了一层,Dart 层调用统一接口,底层分别调用 iOS 和 Android 的原生 SDK。难点在于双端 API 差异的抹平和异步回调的处理。"
如果问性能优化: "Flutter 性能已经很好了,但还是有优化空间。我主要做了三件事:一是用 Isolate 处理数据解析,避免阻塞 UI 线程;二是优化 widget 构建,减少不必要的 rebuild;三是使用本地数据库缓存数据,减少网络请求。优化后列表滑动稳定 60fps。"
数据记忆
- 冷启动 3s → 0.8s
- 缓存命中率 76%
- 包体积减少 30%
- 代码复用率 92%
- 崩溃率 0.1%
- 60fps 流畅体验
- 日活 120 万