Flutter 渲染优化详解
简介
渲染性能直接影响应用的流畅度。本文介绍如何优化 Flutter 应用的渲染性能。
基本概念
渲染流程
- Layout - 计算大小和位置
- Paint - 绘制界面
- Composite - 合成图层
性能指标
- 帧率(FPS)
- 帧时间
- 掉帧数量
优化方法
1. 减少重建
dart
// 使用 const 构造函数
const MyWidget(
key: Key('my_widget'),
title: 'Hello',
);
// 使用 StatelessWidget
class MyWidget extends StatelessWidget {
const MyWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: Text('Hello'),
);
}
}
2. 使用 RepaintBoundary
dart
class OptimizedList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return RepaintBoundary(
child: ListItem(index: index),
);
},
);
}
}
3. 图层优化
dart
// 避免不必要的 Opacity
// 不推荐
Opacity(
opacity: 0.5,
child: ExpensiveWidget(),
);
// 推荐
Container(
color: Colors.black.withOpacity(0.5),
child: ExpensiveWidget(),
);
// 使用 Transform 代替 Positioned
// 不推荐
Stack(
children: [
Positioned(
left: _animation.value,
child: ExpensiveWidget(),
),
],
);
// 推荐
Transform.translate(
offset: Offset(_animation.value, 0),
child: ExpensiveWidget(),
)
完整示例
dart
class RenderOptimizedApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: OptimizedList(),
),
);
}
}
class OptimizedList extends StatefulWidget {
@override
_OptimizedListState createState() => _OptimizedListState();
}
class _OptimizedListState extends State<OptimizedList> {
final ScrollController _controller = ScrollController();
final List<String> _items = List.generate(1000, (i) => 'Item $i');
@override
Widget build(BuildContext context) {
return CustomScrollView(
controller: _controller,
cacheExtent: 100, // 缓存范围
physics: const BouncingScrollPhysics(),
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
// 使用 RepaintBoundary 隔离重绘区域
return RepaintBoundary(
child: _buildItem(index),
);
},
childCount: _items.length,
),
),
],
);
}
Widget _buildItem(int index) {
// 使用 const 构造函数
return const ListItemWidget(
height: 100,
margin: EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
class ListItemWidget extends StatelessWidget {
final double height;
final EdgeInsets margin;
const ListItemWidget({
Key? key,
required this.height,
required this.margin,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: height,
margin: margin,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: const [
BoxShadow(
color: Colors.black12,
offset: Offset(0, 2),
blurRadius: 4,
),
],
),
child: const _ItemContent(),
);
}
}
class _ItemContent extends StatelessWidget {
const _ItemContent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: const [
_ItemImage(),
SizedBox(width: 16),
Expanded(child: _ItemText()),
],
);
}
}
性能监控
1. 性能叠加层
dart
void main() {
runApp(
Directionality(
textDirection: TextDirection.ltr,
child: Stack(
children: [
MyApp(),
const PerformanceOverlay.allEnabled(),
],
),
),
);
}
2. 自定义性能监控
dart
class PerformanceMonitor {
static final stopwatch = Stopwatch();
static int _frameCount = 0;
static double _fps = 0;
static void startMonitoring() {
stopwatch.start();
SchedulerBinding.instance.addPostFrameCallback(_onFrame);
}
static void _onFrame(Duration timestamp) {
_frameCount++;
if (stopwatch.elapsedMilliseconds >= 1000) {
_fps = _frameCount * 1000 / stopwatch.elapsedMilliseconds;
print('FPS: ${_fps.toStringAsFixed(1)}');
_frameCount = 0;
stopwatch.reset();
stopwatch.start();
}
SchedulerBinding.instance.addPostFrameCallback(_onFrame);
}
}
最佳实践
- 使用 const 构造函数
- 合理使用 RepaintBoundary
- 优化图层结构
- 避免不必要的重建
- 监控渲染性能
注意事项
- 避免过度优化
- 平衡性能和代码可读性
- 注意内存占用
- 测试不同设备
- 监控性能指标
总结
渲染优化需要从多个层面入手,包括减少重建、优化图层、合理使用缓存等。通过合理的优化措施,可以显著提升应用的渲染性能和流畅度。