Skip to content

Flutter 性能优化

渲染性能

减少 Widget 重建

dart
// ❌ 避免:整个列表重建
class BadList extends StatelessWidget {
  final List<Item> items;
  
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: items.map((item) => ItemWidget(item)).toList(),
    );
  }
}

// ✅ 推荐:使用 builder 按需创建
class GoodList extends StatelessWidget {
  final List<Item> items;
  
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) => ItemWidget(items[index]),
    );
  }
}

使用 const 构造函数

dart
// ✅ 使用 const,避免重建
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: const [
        Text('Static Text'),  // 不会重建
        Icon(Icons.star),     // 不会重建
      ],
    );
  }
}

RepaintBoundary

dart
// 隔离重绘区域
CustomScrollView(
  slivers: [
    SliverToBoxAdapter(
      child: RepaintBoundary(
        child: ExpensiveWidget(),  // 独立重绘
      ),
    ),
    // 其他 slivers...
  ],
)

列表性能

大列表优化

dart
// 使用 ListView.builder 虚拟化
ListView.builder(
  itemCount: 10000,
  itemBuilder: (context, index) {
    return ListTile(title: Text('Item $index'));
  },
)

// 使用 itemExtent 提升性能(固定高度)
ListView.builder(
  itemCount: 10000,
  itemExtent: 60.0,  // 固定高度
  itemBuilder: (context, index) => ListTile(title: Text('Item $index')),
)

图片列表优化

dart
ListView.builder(
  itemBuilder: (context, index) {
    return Image.network(
      urls[index],
      // 限制缓存大小
      cacheWidth: 200,
      cacheHeight: 200,
      // 使用占位符
      frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
        if (wasSynchronouslyLoaded) return child;
        return AnimatedOpacity(
          opacity: frame == null ? 0 : 1,
          duration: Duration(milliseconds: 300),
          child: child,
        );
      },
    );
  },
)

动画性能

使用 AnimatedBuilder

dart
// ❌ 避免:整个 Widget 重建
class BadAnimation extends StatefulWidget {
  @override
  State<BadAnimation> createState() => _BadAnimationState();
}

class _BadAnimationState extends State<BadAnimation>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  
  @override
  Widget build(BuildContext context) {
    // 整个树重建
    return Transform.rotate(
      angle: _controller.value * 2 * pi,
      child: ExpensiveWidget(),
    );
  }
}

// ✅ 推荐:只重建动画部分
class GoodAnimation extends StatefulWidget {
  @override
  State<GoodAnimation> createState() => _GoodAnimationState();
}

class _GoodAnimationState extends State<GoodAnimation>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  
  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Transform.rotate(
          angle: _controller.value * 2 * pi,
          child: child,  // child 不重建
        );
      },
      child: ExpensiveWidget(),  // 只创建一次
    );
  }
}

内存优化

图片内存管理

dart
// 限制图片缓存
PaintingBinding.instance.imageCache.maximumSize = 100;
PaintingBinding.instance.imageCache.maximumSizeBytes = 50 << 20; // 50MB

// 清理缓存
PaintingBinding.instance.imageCache.clear();

避免内存泄漏

dart
class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late StreamSubscription _subscription;
  late AnimationController _controller;
  
  @override
  void initState() {
    super.initState();
    _subscription = stream.listen((_) {});
    _controller = AnimationController(vsync: this);
  }
  
  @override
  void dispose() {
    // ✅ 必须释放资源
    _subscription.cancel();
    _controller.dispose();
    super.dispose();
  }
}

启动优化

减少启动时加载

dart
// 延迟初始化
late final heavyObject = HeavyClass();

// 异步初始化
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 并行初始化
  await Future.wait([
    SharedPreferences.getInstance(),
    Firebase.initializeApp(),
  ]);
  
  runApp(MyApp());
}

预编译 Shader

bash
# 收集 shader
flutter run --profile --cache-sksl

# 使用 shader 构建
flutter build apk --bundle-sksl-path=flutter_01.sksl.json

性能分析工具

dart
// 开启性能统计
import 'dart:developer' as developer;

void measurePerformance() {
  developer.Timeline.startSync('MyOperation');
  // 执行操作
  developer.Timeline.finishSync();
}

// 使用 DevTools
// flutter run --profile
// 打开 DevTools 的 Performance 面板

面试要点

  1. Widget 重建优化:const、builder、RepaintBoundary
  2. 列表优化:虚拟化、固定高度、图片缓存
  3. 动画优化:AnimatedBuilder 隔离重建
  4. 内存管理:dispose 释放资源、图片缓存控制

前端面试知识库