サブクラス化の代わりに単純な関数を使用してウィジェットを作成できることに気付きましたステートレスウィジェットたとえば次のようになります。
Widget function({ String title, VoidCallback callback }) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
これは、本格的なクラスよりもはるかに少ないコードしか必要としないため興味深いです。例:
class SomeWidget extends StatelessWidget {
final VoidCallback callback;
final String title;
const SomeWidget({Key key, this.callback, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
}
そこで疑問に思ったのですが、ウィジェットを作成するための関数とクラスには、構文以外に何か違いがあるのでしょうか? また、関数を使用するのは良い習慣なのでしょうか?
ベストアンサー1
編集:Flutterチームはこの問題に関して公式の立場を取り、クラスが望ましいと述べました。https://www.youtube.com/watch?v=IOyq-eTRhvo
TL;DR:再利用可能なウィジェット ツリーを作成するには、関数よりもクラスを使用することをお勧めします。
編集: 誤解を補うために: これは関数が問題を引き起こすということではなく、クラスが問題を解決するということについてです。
フラッターはステートレスウィジェット関数が同じことを実行できるかどうか。
同様に、これは主に、再利用されるように作成されたパブリック ウィジェットを対象としています。1 回だけ使用されるように作成されたプライベート関数の場合、それほど問題にはなりませんが、この動作を認識しておくことは依然として良いことです。
クラスの代わりに関数を使用することには重要な違いがあります。つまり、フレームワークは関数を認識しませんが、クラスは認識できます。
次の「ウィジェット」関数を考えてみましょう。
Widget functionWidget({ Widget child}) {
return Container(child: child);
}
次のように使用します:
functionWidget(
child: functionWidget(),
);
そして、それに相当するクラスは次のとおりです。
class ClassWidget extends StatelessWidget {
final Widget child;
const ClassWidget({Key key, this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: child,
);
}
}
次のように使用されます:
new ClassWidget(
child: new ClassWidget(),
);
紙の上では、どちらもまったく同じこと、つまり Create 2 を実行しContainer
、一方が他方にネストされているように見えます。しかし、現実は少し異なります。
関数の場合、生成されたウィジェット ツリーは次のようになります。
Container
Container
クラスの場合、ウィジェット ツリーは次のようになります。
ClassWidget
Container
ClassWidget
Container
これは、ウィジェットを更新するときにフレームワークの動作を変更するため重要です。
それがなぜ重要なのか
関数を使用してウィジェット ツリーを複数のウィジェットに分割すると、バグが発生し、パフォーマンスの最適化が一部失われます。
関数を使用するとバグが発生するという保証はありませんが、クラスを使用すると、これらの問題が発生しないことが保証されます。
問題をよりよく理解するために自分で実行できる、Dartpad 上のインタラクティブな例をいくつか示します。
https://dartpad.dev/?id=bcae5878ccced764b35dd9a659a593db
この例では、アプリを関数に分割すると、次のようなものが誤って壊れる可能性があることを示しています。AnimatedSwitcher
https://dartpad.dev/?id=481a2c301c2e4bed6c30ba651d01bacbこの例では、クラスによってウィジェットツリーをより細かく再構築し、パフォーマンスを向上させる方法を示しています。
https://dartpad.dev/?id=8bcb85ba535102bed652e5bf1540ac3bこの例では、関数を使用することで、BuildContext を誤用し、InheritedWidgets (Theme やプロバイダなど) を使用するときにバグに直面する危険性を示しています。
結論
関数とクラスの使用の違いをまとめたリストを以下に示します。
- クラス:
- パフォーマンスの最適化を可能にする(constコンストラクタ、より細かい再構築)
- 2 つの異なるレイアウトを切り替えるとリソースが正しく破棄されることを確認します (関数は以前の状態を再利用する場合があります)
- ホットリロードが適切に機能することを保証します (関数を使用すると、& のホットリロードが機能しなくなる可能性があります
showDialogs
) - ウィジェット インスペクターに統合されています。
ClassWidget
開発ツールで表示されるウィジェットツリーを見ると、画面に何が表示されているかがわかります。- 上書きできるデバッグフィルプロパティウィジェットに渡されたパラメータを印刷する
- より良いエラーメッセージ
例外が発生した場合(ProviderNotFoundなど)、フレームワークは現在構築中のウィジェットの名前を表示します。ウィジェットツリーを関数+のみに分割した場合Builder
、エラーには役立つ名前が付きません。 - キーを定義できる
- コンテキストAPIを使用できる
- 機能:
- コードが少ない(コード生成で解決できる)機能ウィジェット)
全体として、これらの理由により、ウィジェットを再利用するためにクラスではなく関数を使用するのは悪い習慣だと考えられています。 関数を使用することは
できますが、将来的に問題になる可能性があります。