Skip to content
alex's blog
Go back

Flutter 性能优化实战指南

编辑页面

性能优化是 Flutter 开发中的重要话题。一个性能优秀的应用不仅能提供流畅的用户体验,还能节省设备资源。本文将分享 Flutter 性能优化的实用技巧和最佳实践。

1. 构建优化

使用 const 构造函数

尽可能使用 const 构造函数,可以避免不必要的重建:

// ❌ 不推荐
Widget build(BuildContext context) {
  return Container(
    child: Text('Hello'),
  );
}

// ✅ 推荐
Widget build(BuildContext context) {
  return const Container(
    child: Text('Hello'),
  );
}

拆分 Widget

将大 Widget 拆分成小的 StatelessWidget:

// ❌ 不推荐:所有内容在一个 build 方法中
class MyPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          // 大量代码...
        ],
      ),
    );
  }
}

// ✅ 推荐:拆分成小的 Widget
class MyPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          HeaderWidget(),
          ContentWidget(),
          FooterWidget(),
        ],
      ),
    );
  }
}

class HeaderWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(/* ... */);
  }
}

使用 Builder 延迟构建

ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ItemWidget(item: items[index]);
  },
);

2. ListView 优化

使用 ListView.builder

// ❌ 不推荐:一次性构建所有项
ListView(
  children: items.map((item) => ItemWidget(item: item)).toList(),
)

// ✅ 推荐:按需构建
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ItemWidget(item: items[index]);
  },
)

设置 itemExtent

对于固定高度的列表项,设置 itemExtent 可以提升性能:

ListView.builder(
  itemCount: items.length,
  itemExtent: 80.0, // 固定高度
  itemBuilder: (context, index) {
    return ItemWidget(item: items[index]);
  },
)

使用 cacheExtent

ListView.builder(
  cacheExtent: 500.0, // 预加载范围
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ItemWidget(item: items[index]);
  },
)

3. 图片优化

使用合适的图片格式

// WebP 格式通常比 PNG/JPG 更小
Image.asset('assets/image.webp')

图片缓存

// 使用 cached_network_image
CachedNetworkImage(
  imageUrl: 'https://example.com/image.jpg',
  placeholder: (context, url) => CircularProgressIndicator(),
  errorWidget: (context, url, error) => Icon(Icons.error),
)

图片尺寸优化

// 使用 ResizeImage 调整图片大小
Image(
  image: ResizeImage(
    NetworkImage('https://example.com/large-image.jpg'),
    width: 200,
    height: 200,
  ),
)

4. 状态管理优化

使用 ValueNotifier

对于简单的状态,使用 ValueNotifiersetState 更高效:

class CounterWidget extends StatelessWidget {
  final ValueNotifier<int> counter = ValueNotifier<int>(0);
  
  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<int>(
      valueListenable: counter,
      builder: (context, value, child) {
        return Text('Count: $value');
      },
    );
  }
}

使用 Selector(Provider)

只监听需要的部分状态:

// ❌ 不推荐:监听整个状态
Consumer<UserModel>(
  builder: (context, user, child) {
    return Text(user.name); // 只使用 name,但整个 user 变化都会重建
  },
)

// ✅ 推荐:只监听需要的部分
Selector<UserModel, String>(
  selector: (_, user) => user.name,
  builder: (context, name, child) {
    return Text(name);
  },
)

5. 动画优化

使用 AnimatedBuilder

class AnimatedWidget extends StatefulWidget {
  @override
  _AnimatedWidgetState createState() => _AnimatedWidgetState();
}

class _AnimatedWidgetState extends State<AnimatedWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;
  
  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );
    _animation = Tween<double>(begin: 0, end: 1).animate(_controller);
    _controller.forward();
  }
  
  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return Opacity(
          opacity: _animation.value,
          child: child,
        );
      },
      child: YourWidget(),
    );
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

使用 RepaintBoundary

隔离重绘区域:

RepaintBoundary(
  child: AnimatedWidget(),
)

6. 内存管理

及时释放资源

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

class _MyWidgetState extends State<MyWidget> {
  Timer? _timer;
  StreamSubscription? _subscription;
  
  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(Duration(seconds: 1), (_) {
      // ...
    });
  }
  
  @override
  void dispose() {
    _timer?.cancel();
    _subscription?.cancel();
    super.dispose();
  }
}

使用 WeakReference

// 避免循环引用
class MyController {
  WeakReference<MyWidget>? _widgetRef;
  
  void setWidget(MyWidget widget) {
    _widgetRef = WeakReference(widget);
  }
}

7. 网络请求优化

使用连接池

final httpClient = HttpClient()
  ..maxConnectionsPerHost = 10;

请求去重

class RequestCache {
  static final Map<String, Future> _cache = {};
  
  static Future<T> get<T>(String key, Future<T> Function() fetcher) {
    if (_cache.containsKey(key)) {
      return _cache[key] as Future<T>;
    }
    
    final future = fetcher();
    _cache[key] = future;
    
    future.whenComplete(() {
      _cache.remove(key);
    });
    
    return future;
  }
}

使用 Dio 拦截器

final dio = Dio()
  ..interceptors.add(
    InterceptorsWrapper(
      onRequest: (options, handler) {
        // 添加缓存逻辑
        handler.next(options);
      },
    ),
  );

8. 构建模式优化

使用 Profile 模式测试

flutter run --profile

Release 构建

flutter build apk --release
flutter build ios --release

代码混淆

flutter build apk --release --obfuscate --split-debug-info=./debug-info

9. 性能分析工具

Flutter DevTools

flutter pub global activate devtools
flutter pub global run devtools

使用 Performance Overlay

MaterialApp(
  showPerformanceOverlay: true, // 开发时启用
  // ...
)

使用 Timeline

import 'dart:developer' as developer;

void myFunction() {
  developer.Timeline.startSync('myFunction');
  // 执行代码
  developer.Timeline.finishSync();
}

10. 常见性能问题

避免在 build 方法中创建对象

// ❌ 不推荐
Widget build(BuildContext context) {
  final controller = TextEditingController(); // 每次重建都创建
  return TextField(controller: controller);
}

// ✅ 推荐
class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late final TextEditingController _controller;
  
  @override
  void initState() {
    super.initState();
    _controller = TextEditingController();
  }
  
  @override
  Widget build(BuildContext context) {
    return TextField(controller: _controller);
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

避免不必要的 setState

// ❌ 不推荐:频繁调用 setState
void updateCounter() {
  setState(() {
    _counter++;
  });
}

// ✅ 推荐:使用 ValueNotifier
final counter = ValueNotifier<int>(0);

void updateCounter() {
  counter.value++;
}

性能检查清单

总结

Flutter 性能优化需要从多个方面入手:

  1. 构建优化:使用 const、拆分 Widget
  2. 列表优化:使用 builder、设置 itemExtent
  3. 图片优化:使用合适格式、缓存
  4. 状态管理:选择合适方案、精确监听
  5. 内存管理:及时释放资源
  6. 工具使用:使用 DevTools 分析性能

记住:先测量,再优化。使用性能分析工具找出瓶颈,然后有针对性地优化。


性能优化是一个持续的过程,需要在实际开发中不断实践和总结。希望这些技巧能帮助你构建更高效的 Flutter 应用!


编辑页面
Share this post on:

Previous Post
Flutter Widget 生命周期与构建优化
Next Post
Flutter 导航与路由完全指南