[解決済み】再利用可能なウィジェットを作成するための関数とクラスの違いは何ですか?
質問
ウィジェットを作成する際、サブクラス化するのではなく、関数で作成することが可能であることに気づきました。 ステートレスウィジェット . 例を挙げると、こんな感じです。
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
);
}
}
それで、ずっと気になっていたんです。ウィジェットを作成するための関数とクラスには、構文以外に何か違いがあるのでしょうか?また、関数を使用することは良い習慣なのでしょうか?
どのように解決するのですか?
編集 : Flutterチームはこの件に関して公式のスタンスを取り、クラスが望ましいと述べています。参照 https://www.youtube.com/watch?v=IOyq-eTRhvo
TL;DR: 関数よりクラスを使って 再利用可能 ウィジェットツリーです。
EDIT : 誤解を解くために。 これは、関数が問題を引き起こすのではなく、クラスが問題を解決するということです。
Flutterには ステートレスウィジェット もし関数で同じことができるのなら。
同様に、これは主に再利用されることを前提に作られたパブリックウィジェットに向けられたものです。一度だけ使われるプライベートな関数については、それほど問題にはなりませんが、この挙動を意識することは良いことです。
クラスではなく関数を使う、という重要な違いがあります。フレームワークは関数を認識しませんが、クラスを見ることができます。
次の "widget" 関数を考えてみましょう。
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/1870e726d7e04699bc8f9d78ba71da35
この例では、アプリを関数に分割することでどのようになるかを示しています。 のようなものを誤って壊してしまう可能性があります。AnimatedSwitcher
-
https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1
この例では、クラスによってよりきめ細かく ウィジェットツリーのパフォーマンスを向上させる -
https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
この例では、関数を使用することで BuildContext の誤用や、InheritedWidgets (テーマやプロバイダなど) を使用した場合のバグに直面する可能性があります。
まとめ
ここでは、関数とクラスの使い方の違いを整理してみました。
- クラスです。
- パフォーマンスの最適化を可能にする (const コンストラクタ、より細かいリビルド)
- 2つの異なるレイアウトを切り替えても、リソースを正しく処理できるようにする(関数が以前の状態を再利用する場合がある)。
-
ホットリロードが適切に動作するようにします(関数を使用すると
showDialogs
と同様) -
は、ウィジェットインスペクタに統合されています。
-
私たちは見る
ClassWidget
は、devtool が表示するウィジェットツリーで、これは 画面に表示されている内容を理解するのに役立つ - を上書きすることができます。 デバッグフィルプロパティ ウィジェットに渡されたパラメータが何であるかを表示します。
-
私たちは見る
-
エラーメッセージの改善
例外が発生した場合 (ProviderNotFound など)、フレームワークは現在構築しているウィジェットの名前を表示します。 ウィジェットツリーを関数だけで分割している場合+αBuilder
この場合、エラーに役立つ名前はありません。 - キーを定義することができます。
- コンテキストAPIを使用することができます。
- 機能を紹介します。
- コードが少ない(コード生成で解決可能 ファンクショナルウィジェット )
これらの理由から、ウィジェットを再利用する際にクラスではなく関数を使用することはバッドプラクティスと考えられています。
あなたは
できる
しかし、それは将来的にあなたを苦しめるかもしれません。
関連
-
[解決済み] Flutter give コンテナ 丸みを帯びたボーダー
-
[解決済み] Dartは参照渡しになりますか?[重複あり]
-
[解決済み] ヌル値に対して使用されるヌルチェック演算子
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] メソッドと関数の違いは何ですか?
-
[解決済み] Pythonの旧スタイルのクラスと新スタイルのクラスの違いは何ですか?
-
[解決済み] クロージャ」と「ラムダ」の違いは何ですか?
-
[解決済み] .NETにおけるstructとclassの違いは何ですか?
-
[解決済み] Scalaのオブジェクトとクラスの違い
-
[解決済み] init__と__call__の違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
WindowsでFlutterを設定する際にAndroidのライセンス状態がわからない
-
[解決済み】メッセージ「flutter run: 接続されたデバイスがありません"
-
[解決済み】再利用可能なウィジェットを作成するための関数とクラスの違いは何ですか?
-
[解決済み] ボタンの幅を親と同じにするには?
-
[解決済み] Flutterアプリでインターネット接続が可能かどうかを確認する
-
[解決済み] ListViewの最後までプログラム的にスクロールさせる
-
[解決済み] InkWellでリップルエフェクトが表示されない
-
[解決済み] アップバーのタイトルを中央揃えにする方法
-
[解決済み] TextFieldの外や画面上の任意の場所をクリックした後、flutterのソフト入力キーボードを非表示にする方法は?
-
[解決済み] dispose() の後に setState() が呼ばれる。