こんにちは、開発の片岡です。
システムを実装していて最後に課題となるのは往々にして処理速度・処理性能ですね。
バグもなく、仕様通りのアプリケーションは一見完璧に見えますが、読み込み速度が遅いという一点だけで致命的・・
今日は標題の、Flutterにおけるパフォーマンスを意識した実装について書いていきたいと思います。
Flutterとは何かについてはこちらの記事をご参照ください。
パフォーマンスを意識した実装…実装時に意識することは?
ウィジェットの再構築
build()メソッドの中で、コストのかかる処理をしないこと、そして各ウィジェットが必要最低限の再構築に留められるようにすることが肝要です。
例えば、Aのデータを非同期通信で取得後、取得したデータを表示するために画面を再描画したい時などにはsetState()メソッドが用いられますが、この場合、AだけでなくBやCから様々な種類のデータを取得したい場合にはその回数分setState()メソッドが呼ばれ、build()メソッドが走り画面の再構成が行われることになります。よくある形ですが、これを改善する方法はどんなものがあるのでしょうか。
方法1.変更のあった範囲だけを再構築する
変更のあった範囲だけを再構築することでCPU、GPUの利用コストが低減されます。
以下は一度作られると再構築がされない(≒build()メソッドが呼ばれない)ようにする代表的な手段たちです。
◆BLoCパターン
◆ScopedModalパターン
◆StreamBuilderウィジェット
詳しくはこちらの記事で解説・利用手段など非常に判りやすくまとめてくださっているので、ご参照ください。
方法2. StatefulStateに記載する要素を少なくする
ウィジェットの種類 | 概要 | 使用例 |
StatelessWidget | 状態を持たない静的Widget。不変項目を表示 | アプリ名を表示する上部バナー等 |
StatefulWidget | 状態を持ち、動的に変更可能なWidget 通信/データやユーザー入力による変化を反映する |
・記事やお知らせ一覧 ・住所入力欄 ・登録情報一覧 など |
例えば、StatelessWidgetにウィジェットの記載がまるでなく、全てStatefulWidgetに記載しているというような状態の場合、不変項目はStatelessWidgetに移設するのが良いでしょう。方法1と同じく、再描画(build()メソッド)が走る際に描画対象のウィジェットが出来るだけ少なくなるようにします。
方法3. 奥の手? UI描画の核となるウィジェット-RenderObjectWidgetを呼び出す
他に手がない/行っても支障がない場合に選択できる手段の一つがこちらです。例えばTextウィジェットはRichTextウィジェットを内包しています。パフォーマンスを優先する実装の場合は、こうしたRenderObjectWidgetを直に呼び出して実装するということも取れる方法の一つではあります。ただし可読性が落ちる可能性や、ラップしているウィジェットとは違う動きをする場合もありますので、慎重に見極めて使用するのが良いですね。
まとめ
BLoCパターンは特に解説記事も豊富なプラグインも出ているのでぜひ積極的に活用していきたいところです。
速度改善、頑張っていきましょう〜!