图画优化

1.选择合适的图片格局

SVG 是矢量图形格局,因而能够无损地缩放而不会失真。
PNG 是位图格局,它运用像素网格来表示图画,当被扩大时,会呈现像素锯齿或失真。
SVG 适用于需求可伸缩性和交互性的图画,特别是图标、矢量图形和动画。PNG 适用于静态的位图图画,特别是照片、杂乱的图画或需求保留细节的图画。选择运用哪种格局取决于你的需求和运用场景。

SVG图片体积小,能够削减内存占用。

2.适当的缓存图片

某些网络图片需求被频频展现时,能够选择将其缓存,防止消耗功能。
例如

return CachedNetworkImage(
imageUrl: imageUrl, 
placeholder: (context, url) => CircularProgressIndicator(), 
errorWidget: (context, url, error) => Icon(Icons.error), 
cacheManager: DefaultCacheManager(), // 运用默认的缓存管理器 
);

动画优化

1.运用AnimatiedContainer、AnimatedOpacity等动画组件

这些组件将动画操作交给了GPU处理,而不是CPU,完成了硬件加速。

2.运用AnimatedBuilder组件减小重绘区域

只有当需求更新的部分发生改动时,才进行重绘操作。在运用动画时,保证只对需求动画的部分进行更新,防止整个页面或组件的重绘。能够运用AnimatedBuilder组件来尽可能地减小重绘区域。

示例代码

class ExampleWidget extends StatefulWidget {
  @override
  _ExampleWidgetState createState() => _ExampleWidgetState();
}
class _ExampleWidgetState extends State<ExampleWidget> with TickerProviderStateMixin {
  AnimationController _animationController;
  Animation<double> _animation;
  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(seconds: 1),
    );
    _animation = Tween<double>(begin: 0, end: 1).animate(_animationController);
    _animationController.repeat(reverse: true);
  }
  @override
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
        animation: _animation,
        builder: (context, child) {
          return Opacity(
            opacity: _animation.value,
            child: Container(
              width: 200,
              height: 200,
              color: Colors.blue,
              child: Center(
                child: Text(
                  'Hello, world!',
                  style: TextStyle(fontSize: 24, color: Colors.white),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

在上面的代码中,咱们经过AnimationControllerTween来创建一个循环渐隐循环呈现的动画效果。这时候,如果咱们直接将Opacity组件放到ColumnRow组件中,整个界面都会被重绘,功能开销较大。为了减小重绘区域,咱们运用了AnimatedBuilder组件来尽可能地削减重绘区域。在builder回调中,咱们即将进行动画操作的组件放到Opacity组件内部并将其回来,这样只会对Opacity和其子组件(即上面比如中的Container)进行重绘操作,大大进步了功能。

3.运用LayoutBuilderConstrainedBox等组件来预先核算布局,防止过多的布局核算

在动画过程中,频频的布局核算会导致功能下降。能够经过运用LayoutBuilderConstrainedBox等组件来预先核算布局,并尽量防止在动画过程中履行杂乱的布局操作。

class ExampleWidget extends StatefulWidget {
  @override
  _ExampleWidgetState createState() => _ExampleWidgetState();
}
class _ExampleWidgetState extends State<ExampleWidget> with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  Animation<double> _animation;
  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(seconds: 1),
    );
    _animation = Tween<double>(begin: 0, end: 1).animate(_animationController);
    _animationController.repeat(reverse: true);
  }
  @override
  Widget build(BuildContext context) {
    return Center(
      child: LayoutBuilder(
        builder: (context, constraints) {
          final size = constraints.biggest;
          return ConstrainedBox(
            constraints: BoxConstraints.tight(size),
            child: AnimatedBuilder(
              animation: _animation,
              builder: (context, child) {
                return Stack(
                  children: [
                    Positioned(
                      top: size.height * _animation.value,
                      child: Container(
                        width: size.width,
                        height: size.height,
                        color: Colors.blue,
                      ),
                    ),
                    Positioned(
                      top: size.height * (1 - _animation.value),
                      child: Container(
                        width: size.width,
                        height: size.height,
                        color: Colors.red,
                      ),
                    ),
                  ],
                );
              },
            ),
          );
        },
      ),
    );
  }
}

在上述的代码中,LayoutBuilderbuilder回调会在初始阶段进行一次核算,并获取到父组件给予的最大束缚。然后,将这个束缚作为ConstrainedBox的束缚条件,使得ConstrainedBox的巨细固定为这个束缚。

由于ConstrainedBox的巨细是固定的,即便在动画过程中AnimatedBuilder内部的布局发生变化,ConstrainedBox的巨细也不会改动。这意味着AnimatedBuilder的子组件在每一帧中的位置只需根据固定的巨细进行核算,而不需求重新核算整个布局。

因而,经过运用LayoutBuilderConstrainedBox来预先核算布局,能够防止在动画过程中重复履行杂乱的布局核算,然后进步功能。

4.即时开释动画资源

如果动画没有被封闭,它会继续在后台履行,占用资源。
为了防止这些问题,应该在页面封闭时中止动画并清除相关资源。能够经过在dispose()办法中开释资源的办法来完成。具体来说,能够运用以下代码在dispose()办法中中止动画并开释相关资源:

@override
void dispose() {
  _animationController.dispose();   // 中止动画
  super.dispose();
}

_animationController.dispose()办法会中止动画并开释相关的资源。一起,需求保证调用父类的dispose()办法以开释其他资源。