web-dev-qa-db-ja.com

Flutterのステートフルウィジェットとステートレスウィジェットの関係は何ですか?

ステートフルウィジェットは、ライフタイム内に状態を変更するウィジェットとして定義されます。しかし、StatelessWidgetがその子の1つとしてStatefulWidgetを持つことは非常に一般的な習慣です。 StatelessWidgetをその子の1つとして持っている場合、StatefulWidgetはステートフルになりませんか?

StatelessWidgetのコードの一部としてドキュメントを調べてみましたが、StatelessWidgetStatefulwidgetをその子として持つことができ、_StatelessWidgetのままである方法を理解できませんでした。

Flutterのステートフルウィジェットとステートレスウィジェットの関係と違いは何ですか?

50
user462455

StatelessWidget は、単独ではrebuildしません(ただし、外部イベントからはできます)。 StatefulWidget は可能です。それが黄金律です。

しかしあらゆる種類のウィジェットはいつでもrepaintedできます。

Statelessは、すべてのプロパティがimmutableであり、それらを変更する唯一の方法は、その新しいインスタンスを作成することであることを意味しますウィジェット。それはありませんウィジェットツリーをロックします。

しかし、あなたはあなたの子供のタイプが何であるかを気にするべきではありません。影響はありません。

47
Rémi Rousselet

flutter.io のドキュメントから:

...ここで注意すべき重要な点は、ステートレスウィジェットとステートフルウィジェットの両方が同じように動作することです。それらはすべてのフレームを再構築します。違いは、StatefulWidgetには、フレーム全体に状態データを保存して復元するStateオブジェクトがあることです。

疑問がある場合は、常にこのルールを覚えておいてください。ウィジェットが変更された場合(たとえば、ユーザーがウィジェットと対話する場合)、それはステートフルです。ただし、子が変化に反応している場合、親が変化に反応しなければ、親を含むステートレスウィジェットは引き続きステートレスウィジェットになることができます。

17
Saeed Jassani

StatefulWidget vs StatelessWidget。

enter image description here

StatelessWidget:-可変状態を必要としないウィジェット。

  • ステートレスウィジェットは、ユーザーインターフェイスをより具体的に説明する他のウィジェットのコンステレーションを構築することにより、ユーザーインターフェイスの一部を説明するウィジェットです。構築プロセスは、ユーザーインターフェイスの記述が完全に具体化されるまで再帰的に継続します(たとえば、具体的なRenderObjectsを記述するRenderObjectWidgetsのみで構成されます)。

  • statelessウィジェットは、説明しているユーザーインターフェイスの一部が、オブジェクト自体の構成情報と、ウィジェットが膨張する BuildContext 以外に依存していない場合に役立ちます。動的に変更できるコンポジションの場合、例えば内部クロック駆動状態になっているため、または一部のシステム状態に応じて、StatefulWidgetの使用を検討してください。

class GreenFrog extends StatelessWidget {
  const GreenFrog({ Key key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(color: const Color(0xFF2DBD3A));
  }
}

StatefulWidget:-変更可能な状態を持つウィジェット。

  • ステートフルウィジェットは、説明しているユーザーインターフェイスの一部が動的に変更できる場合に役立ちます。

FlutterがStatefulWidgetを作成すると、Stateオブジェクトが作成されます。このオブジェクトは、そのウィジェットのすべての可変状態が保持される場所です。

状態の概念は、次の2つのことで定義されます。

1)ウィジェットで使用されるデータは変更される場合があります。

2)ウィジェットの構築時に、データを同期的に読み取ることはできません。 (すべての状態は、ビルドメソッドが呼び出されるまでに確立する必要があります)。

StatefulWidgetライフサイクル

ライフサイクルには、次の簡略化された手順があります。

1-createState():-FlutterがStatefulWidgetの構築を指示されると、すぐにcreateState()を呼び出します。

  • ツリー内の指定された場所に、このウィジェットの可変状態を作成します。

  • サブクラスはこのメソッドをオーバーライドして、関連付けられたStateサブクラスの新しく作成されたインスタンスを返す必要があります。

@override
_MyState createState() => _MyState();

2-mounted == true:-すべてのウィジェットにはブールthis.mountedプロパティがあります。 buildContextが割り当てられるとtrueになります。ウィジェットがアンマウントされたときにsetStateを呼び出すとエラーになります。このStateオブジェクトが現在ツリーにあるかどうか。

  • Stateオブジェクトを作成した後、initStateを呼び出す前に、フレームワークは、Stateオブジェクトをに関連付けてStateオブジェクトを「マウント」します
    BuildContext。 Stateオブジェクトは、フレームワークまでマウントされたままです
    _dispose()を呼び出します。その後、フレームワークは
    再構築する状態オブジェクト。

  • Mountがtrueでない限り、setStateを呼び出すのはエラーです。

bool get mounted => _element != null;

3-initState():-これは、ウィジェットの作成時に呼び出される最初のメソッドです(もちろん、クラスコンストラクターの後)。

initStateは一度だけ呼び出されます。 super.initState().を呼び出す必要があります

  • 作成されたウィジェットのインスタンスの特定のBuildContextに依存するデータを初期化します。

  • これらのウィジェットに依存するプロパティをツリーの「親」に初期化します。

  • Streams、ChangeNotifiers、またはこのウィジェットのデータを変更する可能性のある他のオブジェクトをサブスクライブします。

@override
initState() {
  super.initState();
  // Add listeners to this class
  cartItemStream.listen((data) {
    _updateWidget(data);
  });
}

4-didChangeDependencies():-このStateオブジェクトの依存関係が変更されると呼び出されます。

  • このメソッドは、initStateの直後にも呼び出されます。このメソッドからBuildContext.inheritFromWidgetOfExactTypeを呼び出すのは安全です。

  • フレームワークは依存関係の変更後に常にビルドを呼び出すため、サブクラスがこのメソッドをオーバーライドすることはほとんどありません。一部のサブクラスは、依存関係が変更されたときに高価な作業(ネットワークフェッチなど)を行う必要があるため、このメソッドをオーバーライドします。

@protected
@mustCallSuper
void didChangeDependencies() { }

5-build():-ウィジェットによって表されるユーザーインターフェースの一部を記述します。

フレームワークは、さまざまな状況でこのメソッドを呼び出します。

  • InitStateを呼び出した後。
  • DidUpdateWidgetを呼び出した後。
  • SetStateの呼び出しを受信した後。
  • このStateオブジェクトの依存関係が変更された後(たとえば、前のビルドで参照されたInheritedWidgetが変更された場合)。
  • Deactivateを呼び出してから、Stateオブジェクトを別の場所のツリーに再挿入した後。
  • フレームワークは、このメソッドによって返されたウィジェットが既存のサブツリーのルートを更新できるかどうかに応じて、既存のサブツリーを更新するか、サブツリーを削除して新しいサブツリーを拡張することにより、このウィジェットの下のサブツリーをこのメソッドによって返されたウィジェットに置き換えます、Widget.canUpdateを呼び出して決定します。

  • 通常、実装は、このウィジェットのコンストラクタからの情報、指定された BuildContext 、およびこのStateオブジェクトの内部状態で構成された、新しく作成されたウィジェットのコンスタレーションを返します。

@override
  Widget build(BuildContext context, MyButtonState state) {
    ... () { print("color: $color"); } ...
  }

6-didUpdateWidget():-ウィジェット構成が変更されるたびに呼び出されます。

  • 親ウィジェットが再構築し、同じランタイムタイプとWidget.keyを持つ新しいウィジェットを表示するようにツリー内のこの場所を更新するように要求すると、フレームワークはこのStateオブジェクトのウィジェットプロパティを更新して新しいウィジェットを参照し、これを呼び出します前のウィジェットを引数として持つメソッド。

  • このメソッドをオーバーライドして、ウィジェットが変更されたときに応答します(たとえば、暗黙的なアニメーションを開始します)。

  • フレームワークは、didUpdateWidgetを呼び出した後に常にビルドを呼び出します。つまり、didUpdateWidgetのsetStateの呼び出しはすべて冗長です。

@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }

7-setState():-Stateオブジェクトの内部状態を変更するたびに、setStateに渡す関数に変更を加えます。

  • setStateを呼び出すと、このサブツリーのユーザーインターフェイスに影響を与える可能性のある方法でこのオブジェクトの内部状態が変化したことをフレームワークに通知します。ビルドをスケジュールする
    このStateオブジェクト。

  • setStateを呼び出さずに状態を直接変更する場合、フレームワークはビルドをスケジュールせず、このサブツリーのユーザーインターフェイスが更新されて反映されない場合があります新しい状態。

setState(() { _myState = newValue });

8-deactivate():-Stateがツリーから削除されるとDeactivateが呼び出されますが、現在のフレームの変更が完了する前に再挿入される場合があります。このメソッドは基本的に、Stateオブジェクトをツリー内のあるポイントから別のポイントに移動できるために存在します。

  • フレームワークは、このStateオブジェクトをツリーから削除するたびにこのメソッドを呼び出します。場合によっては、フレームワークはStateオブジェクトをツリーの別の部分に再挿入します(たとえば、このStateオブジェクトを含むサブツリーがツリーのある場所から別の場所に移植される場合)。その場合、フレームワークはbuildを呼び出してStateオブジェクトにツリー内の新しい場所に適応する機会を与えます。フレームワークがこのサブツリーを再挿入する場合、サブツリーがツリーから削除されたアニメーションフレームの終了前に挿入します。このため、Stateオブジェクトは、フレームワークがdisposeメソッドを呼び出すまで、ほとんどのリソースの解放を延期できます。

これはめったに使用されません。

@protected
@mustCallSuper
void deactivate() { }

9-dispose():-このオブジェクトが永久にツリーから削除されると呼び出されます。

  • このStateオブジェクトが二度と構築されない場合、フレームワークはこのメソッドを呼び出します。フレームワークがdispose()を呼び出した後、Stateオブジェクトはマウントされていないと見なされ、マウントされたプロパティはfalseです。この時点でsetStateを呼び出すのはエラーです。ライフサイクルのこの段階は最終段階です。破棄されたStateオブジェクトを再マウントする方法はありません。

  • サブクラスはこのメソッドをオーバーライドして、このオブジェクトによって保持されているリソースを解放する必要があります(アクティブなアニメーションを停止するなど)。

@protected
@mustCallSuper
void dispose() {
  assert(_debugLifecycleState == _StateLifecycle.ready);
  assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
}

enter image description here

詳細については hereherehere

14
Farhana

状態とは、(1)ウィジェットの構築時に同期的に読み取ることができ、(2)ウィジェットの有効期間中に変更される可能性がある情報です。 State.setStateを使用して、そのような状態が変更されたときにStateに速やかに通知されるようにすることは、ウィジェットの実装者の責任です。

StatefulWidget

ステートフルウィジェットは、ユーザーインターフェイスをより具体的に記述する他のウィジェットのコンステレーションを構築することにより、ユーザーインターフェイスの一部を記述するウィジェットです。構築プロセスは、ユーザーインターフェイスの記述が完全に具体化されるまで再帰的に継続します(たとえば、具体的なRenderObjectsを記述するRenderObjectWidgetsのみで構成されます)。

ステートフルウィジェットは、説明しているユーザーインターフェイスの一部が動的に変更できる場合に役立ちます。内部クロック駆動状態にあるため、またはいくつかのシステム状態に依存します。オブジェクト自体の構成情報とウィジェットが拡張されるBuildContextのみに依存するコンポジションの場合は、StatelessWidgetの使用を検討してください。

StatefulWidgetインスタンス自体は不変であり、createStateメソッドによって作成された個別のStateオブジェクト、またはStatefulWidgetの最終フィールドに参照が格納されるStreamまたはChangeNotifierオブジェクトなど、そのStateがサブスクライブするオブジェクトのいずれかに、可変状態を格納します自体。

StatelessWidget

ステートレスウィジェットは、ユーザーインターフェイスをより具体的に説明する他のウィジェットのコンステレーションを構築することにより、ユーザーインターフェイスの一部を説明するウィジェットです。構築プロセスは、ユーザーインターフェイスの記述が完全に具体化されるまで再帰的に継続します(たとえば、具体的なRenderObjectsを記述するRenderObjectWidgetsのみで構成されます)。

ステートレスウィジェットは、説明するユーザーインターフェイスの一部が、オブジェクト自体の構成情報と、ウィジェットが拡張されるBuildContext以外に依存しない場合に役立ちます。動的に変更できるコンポジションの場合、例えば内部クロック駆動状態を持つため、またはシステムの状態によっては、StatefulWidgetの使用を検討してください。

10
Krunal

Flutter docsで言及されているように

ポイントは何ですか?

一部のウィジェットはステートフルで、一部のウィジェットはステートレスです。ウィジェットが変更された場合(たとえば、ユーザーがウィジェットと対話する場合)、それはステートフルです。ウィジェットの状態は、スライダーの現在の値やチェックボックスがオンになっているかどうかなど、変更可能な値で構成されています。ウィジェットの状態はStateオブジェクトに格納され、ウィジェットの状態と外観を分離します。ウィジェットの状態が変更されると、状態オブジェクトはsetState()を呼び出し、フレームワークにウィジェットを再描画するよう指示します。

ステートレスウィジェットには、管理する内部状態がありません。 Icon、IconButton、およびTextは、StatelessWidgetのサブクラスであるステートレスウィジェットの例です。

ステートフルウィジェットは動的です。ユーザーは、ステートフルウィジェット(フォームへの入力やスライダーの移動など)と対話したり、時間の経過とともに変化したりする可能性があります(データフィードによってUIが更新される可能性があります)。 Checkbox、Radio、Slider、InkWell、Form、およびTextFieldは、StatefulWidgetのサブクラスであるステートフルウィジェットの例です。

https://flutter.io/tutorials/interactive/#stateful-stateless

8
Ulearn

ステートフルネスとステートレスネスに関するStackOverflowの質問

Flutterの違いは、すべてのコンストラクター引数だけでステートレスウィジェットを定義できることです。同じ引数を使用して2つのステートレスウィジェットを作成する場合、それらは同じになります。

ただし、ステートフルウィジェットは、同じコンストラクター引数で構築された別のウィジェットと必ずしも同じではありません。別の状態である可能性があります。
実際、ステートフルwidgetは不変(ステートレス)ですが、Flutterは別の状態を管理しますobjectおよび StatefulWidget doc で説明されているように、それをウィジェットに関連付けます。つまり、Flutterはステートフルウィジェットを再構築するときに、以前の状態オブジェクトを再利用する必要があるかどうかを確認し、必要に応じてその状態オブジェクトをウィジェットにアタッチします。

親ウィジェットは、子の状態を考慮しないため、ステートレスです。ステートフルな子自体(または技術的にはFlutter)は、自身の状態を処理します。
高レベルでは、親ウィジェットがステートフルになることに同意します。2つの親が異なる状態の2つの子を含む可能性があるため、技術的に異なるためです。しかし、Flutterの観点からは、状態を気にせずに親ウィジェットを構築し、子を構築する場合にのみ、そのステートフルネスを考慮します。

5
J0hj0h

ステートレスウィジェットは静的ウィジェットです。ステートレスウィジェットを初期化する前に、いくつかのプロパティを渡すだけです。データの変更や動作の変更には依存しません。例えば。テキスト、アイコン、RaisedButtonはステートレスウィジェットです。

ステートフルウィジェットは動的ウィジェットであり、ユーザーのアクションまたはデータの変更に基づいて実行時に更新できます。実行時にウィジェットの状態を変更できる場合、ウィジェットはステートフルウィジェットになります。

2018年11月15日編集

Stateless Widgetsは、入力/外部データが変更された場合に再レンダリングできます(外部データはコンストラクターを介して渡されるデータです)。ステートレスウィジェットには状態がないため、一度レンダリングされて自身は更新されませんが、外部データが変更された場合にのみ更新されます。

一方、Stateful Widgetsは内部状態を持ち、入力データが変更された場合、またはウィジェットの状態が変更された場合に再レンダリングできます。

ステートレスウィジェットとステートフルウィジェットのライフサイクルは異なります。

5
Hammad Tariq