Flutter

【Flutter】パフォーマンス改善(Use ‘const’ with the constructor to improve performance.)の対処法

Flutter

こんにちは。

今回はFlutterのパフォーマンス改善の中でも定数オブジェクトを生成する「const」に着目して調べたことをまとめたいと思います。実装をしていると「Use 'const' with the constructor to improve performance.」と警告が出る場合がありますが、その内容についても触れていきます。

constとは

Flutterにおけるconstは、定数(constant)Widgetや不変のオブジェクトを表すために使用されます。Dartでは、constはコンパイル時に値が確定するオブジェクトの宣言に使われ、FlutterのWidgetツリーのパフォーマンスを最適化するために重要な役割を果たします。

constの役割とメリット

1. 定数インスタンスを生成

constを使うことで、不変のWidgetインスタンスが作られます。このインスタンスは一度生成されると再利用され、同じ内容で再生成する必要がなくなるため、レンダリング時のパフォーマンスが向上します。

2. 再レンダリングの回避

constで作られたWidgetは、Flutterの再ビルドの際に状態が変わらない限り再描画されません。これにより、Widgetツリー全体での再レンダリングを減らし、アプリの動作を効率的にします。

3. メモリ使用量の削減

同じconstインスタンスは再利用されるため、複数の箇所で同じWidgetや値を使う際にメモリの節約になります。

以下はドキュメントから引っ張ってきたコードですが、同じ内容を持つ2つの定数インスタンスを作成しようとした場合、Dartはそれらを1つの共有されたインスタンスとして扱っています。

var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);

assert(identical(a, b)); // They are the same instance!

 

一方で定数でないオブジェクトの場合は、異なるインスタンスとして扱われます。

var a = const ImmutablePoint(1, 1); // Creates a constant
var b = ImmutablePoint(1, 1); // Does NOT create a constant

assert(!identical(a, b)); // NOT the same instance!

constの使用が適切な場面

  • StatelessWidgetで不変のプロパティを使う場合
  • 再利用できるWidgetの場合(アイコンや静的なテキストなど)
  • コンパイル時に確定する値(リスト、マップなど)を生成する場合

注意点

  • 状態を持つWidgetや動的に変化する内容には使用できない
  • パフォーマンス最適化のために、可能な限りconstを活用することが推奨されるが、むやみにconstを付けるのではなく、不変であることが確実な箇所にのみ付けるのが理想

Use ‘const’ with the constructor to improve performance.

警告例

flutter_lintを入れていると、constが必要な箇所にconstが書かれていない場合「Use 'const' with the constructor to improve performance.
Try adding the 'const' keyword to the constructor invocation.」と警告が出されます。

この警告箇所にconstを記述することでこの警告は解除されます。

constの書き忘れを防ぎ、パフォーマス改善に繋げてくれるのでflutter_lintはONにしておくことをおすすめします。

flutter_lintはanalysis_options.yamlで設定することができます。

# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
  # The lint rules applied to this project can be customized in the
  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
  # included above or to enable additional rules. A list of all available lints
  # and their documentation is published at https://dart.dev/lints.
  #
  # Instead of disabling a lint rule for the entire project in the
  # section below, it can also be suppressed for a single line of code
  # or a specific dart file by using the `// ignore: name_of_lint` and
  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
  # producing the lint.
  rules:
    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

補足

多数のconstがネスト構造的に使用されている場合、定数オブジェクト内ではconstは不要になります。(≒ constが自明である場合は省略できます。)

例えば以下のようなコードでは、定数オブジェクト内で多数のconstが使用されています。

// 多数の const が使用されている例
const pointAndLine = const {
  'point': const [const ImmutablePoint(0, 0)],
  'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};

 

これは以下のようにconstを省略して記載することができます。

// 最初の const だけで定数コンテキストを確立する例
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};

まとめ

  • Flutterにおけるconstは、定数Widgetや不変のオブジェクトを表し、コンパイル時に値が確定するオブジェクトを生成する
  • 不変のWidgetインスタンスを作成し、同じ内容で再生成を避けることでパフォーマンスが向上する
  • const Widgetは再ビルド時も再描画されないため、アプリの効率が向上する
  • constを定義することで同じインスタンスが再利用され、メモリの節約に役立つ
  • flutter_lintを利用することで、constの不足を防ぎ、パフォーマンス改善に役立つ
  • 定数オブジェクト内では、最初のconstだけで定数コンテキストが確立されるため、ネストされたconstを省略できる

参考

https://dart.dev/language/classes#using-constructors

 

今回はFlutterのパフォーマンス改善の中でもconstに着目してまとめました。実装をしていると「Use 'const' with the constructor to improve performance.」という警告をよく目にするので、この機会にちゃんと理解することができてよかったと思います。