1. ホーム
  2. ヒラメキ

[解決済み】再利用可能なウィジェットを作成するための関数とクラスの違いは何ですか?

2022-04-19 14:15:46

質問

ウィジェットを作成する際、サブクラス化するのではなく、関数で作成することが可能であることに気づきました。 ステートレスウィジェット . 例を挙げると、こんな感じです。

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にあるインタラクティブな例をいくつか紹介しますので、ご自身で実行してみて、問題をよりよく理解してください。

まとめ

ここでは、関数とクラスの使い方の違いを整理してみました。

  1. クラスです。
  • パフォーマンスの最適化を可能にする (const コンストラクタ、より細かいリビルド)
  • 2つの異なるレイアウトを切り替えても、リソースを正しく処理できるようにする(関数が以前の状態を再利用する場合がある)。
  • ホットリロードが適切に動作するようにします(関数を使用すると showDialogs と同様)
  • は、ウィジェットインスペクタに統合されています。
    • 私たちは見る ClassWidget は、devtool が表示するウィジェットツリーで、これは 画面に表示されている内容を理解するのに役立つ
    • を上書きすることができます。 デバッグフィルプロパティ ウィジェットに渡されたパラメータが何であるかを表示します。
  • エラーメッセージの改善

    例外が発生した場合 (ProviderNotFound など)、フレームワークは現在構築しているウィジェットの名前を表示します。 ウィジェットツリーを関数だけで分割している場合+α Builder この場合、エラーに役立つ名前はありません。
  • キーを定義することができます。
  • コンテキストAPIを使用することができます。
  1. 機能を紹介します。

これらの理由から、ウィジェットを再利用する際にクラスではなく関数を使用することはバッドプラクティスと考えられています。

あなたは できる しかし、それは将来的にあなたを苦しめるかもしれません。