提高Flutter App性能的几个小技巧

遇没遇到性能问题,这些小技巧都值得关注。如果遇到了,他们可以帮助你发现和解决这些问题。如果还没有注意到,这些可以让你预防。也可以让解决这些问题的时候不至于手忙脚乱。

使用WidgetsBindingObserver来跟踪App的生命周期

使用WidgtesBindingObserver来跟踪app的生命周期。使用这个widget可以捕捉到app的pauseresume等的回调,这样可以帮助开发者快速定位到app的性能瓶颈在哪里。

dart 复制代码
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }
  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    // Handle state changes here
  }
  //...
}

使用RepaintBoundary隔绝部分widget

使用RepaintBoundary widget可以把造成性能问题的那一部分widget和app的其他部分隔离。只要用这个widget把可能有性能问题的widget包起来就完成了隔离。

dart 复制代码
RepaintBoundary(
  child: MyExpensiveWidget(),
);

使用InheritedWidget传递数据

组成app的widget最终会形成一个树形结构。在传递数据的时候如果直接作为widget的参数传递不仅写起来麻烦也会造成不必要的重绘。使用InheritedWidget可以直接将数据从一个widget传到另外一个。

dart 复制代码
class MyInheritedWidget extends InheritedWidget {
  final int myData;

  MyInheritedWidget({
    Key key,
    @required this.myData,
    @required Widget child,
  }) : super(key: key, child: child);

  @override
  bool updateShouldNotify(MyInheritedWidget old) => myData != old.myData;

  static MyInheritedWidget of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
  }
}

多用StreamBuilder少用FutureBuilder

尽量多使用StreamBuilder,少用FutureBuilderStreamBuilder会在收到流发出的事件之后才更新,也就是必要时才更新。这样会减少绘制的次数改善性能。

dart 复制代码
StreamBuilder(
  stream: myStream,
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    if (snapshot.hasData) {
      return Text(snapshot.data);
    } else if (snapshot.hasError) {
      return Text(snapshot.error);
    }
    return CircularProgressIndicator();
  },
);

列表尽量使用CustomScrollView

尽量使用CustomScrollView,因为它只会回执可见区域的widget。

dart 复制代码
CustomScrollView(
  slivers: <Widget>[
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return MyListItem(data: myData[index]);
        },
        childCount: myData.length,
      ),
    ),
  ],
);

使用AnimationController控制动画

AnimationController可以控制动画的时间和进展,可以减少widget的重绘,改善性能。

dart 复制代码
class MyAnimationWidget extends StatefulWidget {
  @override
  _MyAnimationWidgetState createState() => _MyAnimationWidgetState();
}

class _MyAnimationWidgetState extends State<MyAnimationWidget>
    with SingleTickerProvider{
    AnimationController _controller;

    @override
    void initState() {
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
    super.initState();
    }

    @override
    void dispose() {
    _controller.dispose();
    super.dispose();
    }

    @override
    Widget build(BuildContext context) {
        return AnimatedBuilder(
        animation: _controller,
        builder: (context, child) {
        // Use _controller.value to control the animation
        return Transform.translate(
        offset: Offset(0, _controller.value * 100),
        child: child,
        );
        },
        child: MyChildWidget(),
        );
    }
}

尽量使用Wrap代替ListView

WrapListView更加高效。因为它同样只绘制可见区域的widget。

dart 复制代码
Wrap(
  children: myChildren.map((child) => MyChildWidget(child)).toList(),
);

使用CustomPainter绘制复杂图形

CustomPainter绘制更加高效,尤其是在绘制复杂的图形或者存在嵌套的时候。

dart 复制代码
class MyCustomPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // Draw complex graphics on the canvas
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

使用PerformanceOverlay实时呈现app的性能

PerformanceOverlay可以实时图形化的展现app的性能。

dart 复制代码
PerformanceOverlay(
  enabled: true,
  overlayRect: Rect.fromLTWH(0, 0, 200, 200),
  children: [
    // Your widgets
  ],
);

使用Dart内置的Profile和Release模式测试性能

dart语言内置了ProfileRelease两个模式来测试性能。Profile模式有详细的性能数据。Release模式则是为app的性能做了优化这样来发现和解决性能问题。

bash 复制代码
flutter run --profile

Release模式:

bash 复制代码
flutter run --release

最后

此文例子其实不够详细,建议也难免有些武断。但是,作为参考可以提供一些不同的思路。

原文地址:dev.to/yatendra200...

相关推荐
CYRUS_STUDIO34 分钟前
用 Frida 控制 Android 线程:kill 命令、挂起与恢复全解析
android·linux·逆向
CYRUS_STUDIO39 分钟前
Frida 实战:Android JNI 数组 (jobjectArray) 操作全流程解析
android·逆向
叫我詹躲躲41 分钟前
n8n 自动化工作流平台完整部署
前端·langchain·领域驱动设计
遂心_2 小时前
为什么 '1'.toString() 可以调用?深入理解 JavaScript 包装对象机制
前端·javascript
IT_陈寒2 小时前
JavaScript 性能优化:5 个被低估的 V8 引擎技巧让你的代码快 200%
前端·人工智能·后端
岛风风3 小时前
关于手机的设备信息
前端
ReturnTrue8683 小时前
nginx性能优化之Gzip
前端
w_y_fan4 小时前
Flutter 滚动组件总结
前端·flutter
wuli金居哇4 小时前
我用 Turborepo 搭了个 Monorepo 脚手架,开发体验直接起飞!
前端
Asort4 小时前
JavaScript 从零开始(五):运算符和表达式——从零开始掌握算术、比较与逻辑运算
前端·javascript