FlutterのWidget生成のパフォーマンスを改善する3つのポイント
こちらの記事はFlutter meetupで登壇した内容を記事にしたものです。
FlutterはWidgetの組み合わせで素早くレイアウトを作成することができる素晴らしいSDKだと思います。
ですが、何も知らずにレイアウトを組んでいると非常に重いレイアウトができ操作しているとカクツイたりしてUXが落ちてしまう可能性があります。
そこで今回はレイアウトの生成ロジックを改善するための3つの指針について紹介します。
前提
前提としてレイアウトが重くなる原因は「Widgetの生成回数が多い」ことが原因です。今回紹介する3つの指針の全てはWidgetの生成回数を減らすための指針になります。
3つの指針
3つの指針は下記です。
1、setState({})は使わない
2、StatelessWidgetを使う
3、変更がないWidgetにはconstをつける
一つ一つ説明していきます。
1、setState({})は使わない
いきなり「え?」ってなりそうなタイトルだと思います。
なぜなら、Flutter始めたときのやる、codelabとかではsetState({})はたくさん使って実装されています。
が、setState({})を実行したときにレイアウトにもよりますが比較的に重い処理が走っています。
具体的には、レイアウトを作り直しています。もっと細かくというと、build()メソッドは以下のレイアウトを作り直しています。
@override
Widget build(BuildContext context) {
// ↓この配下のWidgetを作り直している
return Scaffold(
)
}
ここでたくさんのレイアウトを生成していたりするとそれが一気に変更になってしまうので、重くなります。
一番気をつけるべきは StreamBuilderのbuilderの中でsetState({})することです。
StreamBuilder(stream: chatHelper.getMessages(group.id).asBroadcastStream(), builder: (context, snapshot) {
// なんかの処理
setState(() {});
}
これをやると、setState({})によってStreamBuilderも作り直すのでもう一度非同期処理や、Streamを設定したりしてしまいます。
ですので、基本的には使わない方が自分はいいと考えています。
使うべきところは、BottomNavigationのアイテムタップイベントなどでbuild配下のレイアウトを意図的に変えたいときだけ使うのをお勧めします。
setState({})を回避するためにどうしたらいいか
まず一つにStreamBuilderとFutureBuilderを使いましょう。
動作的にはstream属性、future属性で変更を監視したり、非同期でデータを取得したときにbuilder内で生成しているWidgetだけ更新します。
個人的にStreamBuilderはFlutterのWidgetの中で最高傑作だと思っています。
2、StatelessWidgetを使う
StatelessWidgetはレイアウトを一回実装したら変わりません。
StreamBuilderやFutureBuilderとかを使った場合はbuilderの中だけ変更できるので、別ですが基本的にレイアウトは変更されません。
なので、大きく変更するWidgetと変更しないWidgetをしっかり分けることが大事だと思います。
3、変更がないWidgetにはconstをつける
Widgetにconstをつけることで、Widgetを再利用できます。
ですので、できるだけつけましょう。
まとめ
1、setState({})は使わない
2、StatelessWidgetを使う
3、変更がないWidgetにはconstをつける
あまり深く書きすぎると、読むのが辛くなってしまうと重い、ガイドライン的な記事にしてみました。
なにか質問とかあればTwitterまで連絡ください。
チャットアプリを運用しています。毎日少しずつアプリを実装しているのでよければダウンロードお願いします。
投げ銭はいりません。それより無料でできる拡散をしてください!! 感想をツイートしていただけることが一番嬉しいです!!