Flutter AnimationController重复3次后卡顿严重,求解决方案
Flutter线条动画卡顿优化方案
1. 优化动画控制器的重复逻辑
你当前通过addListener每帧判断动画是否完成,这种方式会产生不必要的高频回调。改用addStatusListener仅在动画状态变化时处理重复逻辑,能大幅减少回调次数:
// 初始化控制器 _controller = AnimationController( duration: Duration(seconds: _roundDuration), vsync: this ); // 替换原addListener为addStatusListener _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { _sets--; if (_sets > 0) { _controller.reset(); _controller.forward(); } else { _controller.stop(); } } }); super.initState();
2. 复用Paint对象,避免重复创建
Paint属于开销较高的资源,你当前在paint方法内每次都重新创建,会累积性能损耗。将其改为类的静态成员复用:
class MyPainter extends CustomPainter { final double percentValue; final int moveDuration; final int holdDuration; // 静态复用Paint对象 static final holdingLinePaint = Paint() ..strokeWidth = 40 ..color = Colors.amber ..strokeCap = StrokeCap.round; static final linePaint = Paint() ..strokeWidth = 40 ..color = Colors.red ..strokeCap = StrokeCap.round; // 预计算固定值,避免每帧重复计算 final double totalDuration; final double firstEndX; final double secondEndX; MyPainter({ required this.percentValue, required this.moveDuration, required this.holdDuration, }) : totalDuration = 2 * moveDuration + holdDuration, firstEndX = (380 / (2 * moveDuration + holdDuration)) * moveDuration + 10.0, secondEndX = (moveDuration + holdDuration) / (2 * moveDuration + holdDuration) * 380 + 10.0; @override void paint(Canvas canvas, Size size) { const lineLength = 380; const leftPadding = 10.0; final dy = size.height / 2; final lineStart = Offset(leftPadding, dy); final lineEnd = Offset(percentValue * 380 + leftPadding, dy); final firstEnd = Offset(firstEndX, dy); final secondEnd = Offset(secondEndX, dy); canvas.drawCircle(firstEnd, 10, Paint()); canvas.drawCircle(secondEnd, 10, Paint()); // 原有的阶段判断逻辑保持不变,替换Paint为静态对象 if (percentValue < (moveDuration / totalDuration)) { canvas.drawLine(lineStart, lineEnd, linePaint); } else if (percentValue >= (moveDuration / totalDuration) && percentValue < (moveDuration + holdDuration) / totalDuration) { canvas.drawLine(firstEnd, lineEnd, holdingLinePaint); canvas.drawLine(lineStart, firstEnd, linePaint); } else { canvas.drawLine(secondEnd, lineEnd, linePaint); canvas.drawLine(firstEnd, secondEnd, holdingLinePaint); canvas.drawLine(lineStart, firstEnd, linePaint); } }
3. 精准控制重绘时机
当前shouldRepaint始终返回true,会导致每帧都强制重绘,即使参数没有变化。修改为仅在必要时触发重绘:
@override bool shouldRepaint(covariant MyPainter oldDelegate) { return percentValue != oldDelegate.percentValue || moveDuration != oldDelegate.moveDuration || holdDuration != oldDelegate.holdDuration; }
4. 额外优化建议
- 确保在
dispose方法中正确释放动画控制器:@override void dispose() { _controller.dispose(); super.dispose(); } - 如果
_roundDuration、_moveDuration、_holdDuration是固定值,建议定义为常量,避免运行时重复计算。
内容的提问来源于stack exchange,提问作者Fever
相关产品推荐
相关产品推荐

