提高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...

相关推荐
下雪天的夏风1 分钟前
TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错
前端·javascript·typescript
diygwcom13 分钟前
electron-updater实现electron全量版本更新
前端·javascript·electron
试行22 分钟前
Android实现自定义下拉列表绑定数据
android·java
Hello-Mr.Wang30 分钟前
vue3中开发引导页的方法
开发语言·前端·javascript
程序员凡尘1 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js
编程零零七4 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
Dingdangr5 小时前
Android中的Intent的作用
android
技术无疆5 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
GEEKVIP5 小时前
Android 恢复挑战和解决方案:如何从 Android 设备恢复删除的文件
android·笔记·安全·macos·智能手机·电脑·笔记本电脑
(⊙o⊙)~哦6 小时前
JavaScript substring() 方法
前端