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


105

ステートフルウィジェットは、その存続期間内にその状態を変更するウィジェットとして定義されます。しかし、aStatelessWidgetStatefulWidgetその子の1つとして持つことは非常に一般的な方法です。子の一人にStatelessWidgetなったらステートフルになりませんStatefulWidgetか?

のコードの一部としてドキュメントを調べてみましたが、が子としてStatelessWidgetどのように保持され、まだ残っStatelessWidgetているのか理解できませんでした。StatefulwidgetStatelessWidget

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


2
さまざまなタイプのウィジェットからレイアウトを構成できますが、それは、各ウィジェットに影響を与えるために構成の特性を継承しているという意味ではありません。つまり、ステートレスで、別の場所でStatefulWidgetとして宣言されている別のコンテナーの子を持つコンテナーを作成できます。コンテナーの状態は、この1つのコンポーネントにのみ影響します。つまり、さまざまな種類のウィジェットから構成を作成し、それぞれが必要に応じて機能するようにすることがすべてです。
aziza 2017年

1
さらに混乱させるために、3番目のタイプのウィジェットがあります:InheritedWidget; どちらがStatelessWidget更新できますか。
レミRousselet

回答:


103

A StatelessWidgetは決して再構築していない自分自身(しかし、外部事象から缶)で。A StatefulWidgetができます。それが黄金律です。

しかし、どんな種類のウィジェットでもいつでも塗り直すことができます。

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

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


11
(フレームワークには比較的新しい)。違いは何であるrebuildrepaint
user462455

また、フラッターフレームワークコードのコメントから、明らかにStateFulWidgetsも不変です。
user462455 2017年

3
ウィジェットのビルドは、基本的に「build」メソッドの呼び出しであり、その後に対応するレンダーボックスを作成/更新します。その後、塗装プロセスが行われます。これらのレンダーボックスを画面に印刷します。
レミRousselet

「StatefulWidget」を継承するクラスは不変です。ただし、状態(State <YourWidget>)自体は変更可能です。
レミRousselet

1
@RémiRousseletステートフルウィジェットとステートレスウィジェットはどちらも、flutter.dev / docs / get
マット

82

StatefulWidgetとStatelessWidget。

ここに画像の説明を入力してください

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

  • ステートレスウィジェットは、ユーザーインターフェイスをより具体的に説明する他のウィジェットのコンステレーションを構築することにより、ユーザーインターフェイスの一部を説明するウィジェットです。構築プロセスは、ユーザーインターフェイスの説明が完全に具体的になるまで再帰的に続行されます(たとえば、具体的なRenderObjectを説明する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)ウィジェットの作成時にデータを同期的に読み取ることができません。(すべての状態は、buildメソッドが呼び出されるまでに確立される必要があります)。

StatefulWidgetのライフサイクル

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

  1. createState() -FlutterがStatefulWidgetを構築するように指示されると、すぐにcreateState()。を呼び出します。
  • ツリー内の特定の場所に、このウィジェットの可変状態を作成します。

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

@override
_MyState createState() => _MyState();
  1. Mounted == true-すべてのウィジェットにはboolthis.mountedプロパティがあります。buildContextが割り当てられるとtrueになります。setStateウィジェットがアンマウントされているときに呼び出すとエラーになります。このStateオブジェクトが現在ツリー内にあるかどうか。
  • Stateオブジェクトを作成した後、を呼び出す前initStateに、フレームワークはStateオブジェクトを。に関連付けて「マウント」します
    BuildContext。状態オブジェクトは、フレームワークが
    呼び出すまでマウントされたままになりますdispose()。その後、フレームワークは
    状態オブジェクトに再構築を要求しません。

  • マウントがtrueでない限り、setStateを呼び出すとエラーになります。

bool get mounted => _element != null;
  1. initState() -これは、ウィジェットが作成されたときに呼び出される最初のメソッドです(もちろん、クラスコンストラクターの後)。

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

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

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

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

@override
initState() {
  super.initState();
  // Add listeners to this class
  cartItemStream.listen((data) {
    _updateWidget(data);
  });
}
  1. didChangeDependencies() -このStateオブジェクトの依存関係が変更されたときに呼び出されます。
  • このメソッドは、の直後にも呼び出されinitStateます。BuildContext.inheritFromWidgetOfExactTypeこのメソッドから呼び出しても安全です。

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

@protected
@mustCallSuper
void didChangeDependencies() { }
  1. build() -ウィジェットによって表されるユーザーインターフェイスの部分を記述します。

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

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

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

@override
  Widget build(BuildContext context, MyButtonState state) {
    ... () { print("color: $color"); } ...
  }
  1. didUpdateWidget() -ウィジェットの構成が変更されるたびに呼び出されます。
  • 親ウィジェットを再構築し、ツリー内のこの場所を更新して、同じランタイムタイプとWidget.keyを持つ新しいウィジェットを表示するように要求すると、フレームワークはこのStateオブジェクトのウィジェットプロパティを更新して、新しいウィジェットを参照し、これを呼び出します。前のウィジェットを引数として持つメソッド。

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

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

@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
  1. setState() -Stateオブジェクトの内部状態を変更するときはいつでも、渡す関数に変更を加えますsetState
  • setStateを呼び出すと、このサブツリーのユーザーインターフェイスに影響を与える可能性のある方法でこのオブジェクトの内部状態が変更されたことがフレームワークに通知され
    ます。これにより、フレームワークはこのStateオブジェクトのビルドをスケジュールします。

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

setState(() { _myState = newValue });
  1. deactivate() -状態がツリーから削除されるとアクティブ化が呼び出されますが、現在のフレーム変更が完了する前に再挿入される場合があります。このメソッドは基本的に、Stateオブジェクトをツリー内のあるポイントから別のポイントに移動できるために存在します。
  • フレームワークは、このStateオブジェクトをツリーから削除するたびに、このメソッドを呼び出します。場合によっては、フレームワークはStateオブジェクトをツリーの別の部分に再挿入します(たとえば、このStateオブジェクトを含むサブツリーがツリー内のある場所から別の場所に移植されている場合)。その場合、フレームワークはbuildを呼び出して、Stateオブジェクトがツリー内の新しい場所に適応する機会を与えるようにします。フレームワークがこのサブツリーを再挿入する場合、サブツリーがツリーから削除されたアニメーションフレームが終了する前に再挿入します。このため、Stateオブジェクトは、フレームワークがdisposeメソッドを呼び出すまで、ほとんどのリソースの解放を延期できます。

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

@protected
@mustCallSuper
void deactivate() { }
  1. dispose() -このオブジェクトがツリーから完全に削除されたときに呼び出されます。
  • このStateオブジェクトが二度とビルドされない場合、フレームワークはこのメソッドを呼び出します。フレームワークがを呼び出したdispose()後、Stateオブジェクトはマウントされていないと見なされ、マウントされたプロパティはfalseです。この時点でsetStateを呼び出すのはエラーです。ライフサイクルのこの段階は最終的なものです。破棄されたStateオブジェクトを再マウントする方法はありません。

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

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

ここに画像の説明を入力してください

詳しくは行くここ 、ここここに


26

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

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

疑わしい場合は、常にこのルールを覚えておいてください。ウィジェットが変更された場合(たとえば、ユーザーがウィジェットを操作した場合)、それはステートフルです。ただし、子が変更に反応している場合、親が変更に反応しなければ、含まれている親はステートレスウィジェットである可能性があります。


14

フラッタードキュメントで言及されているように

ポイントは何ですか?

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

ステートレスウィジェットは管理するためには内部状態を持っていません。Icon、IconButton、およびTextは、StatelessWidgetをサブクラス化するステートレスウィジェットの例です。

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

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


10

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

StatefulWidget

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

ステートフルウィジェットは、説明しているユーザーインターフェイスの一部が動的に変化する可能性がある場合に役立ちます。たとえば、内部のクロック駆動状態がある場合や、システムの状態によって異なります。オブジェクト自体の構成情報とウィジェットが拡張されるBuildContextのみに依存する構成の場合は、StatelessWidgetの使用を検討してください。

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

StatelessWidget

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

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


9

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

ステートフルウィジェットは動的ウィジェットであり、ユーザーの操作やデータの変更に基づいて実行時に更新できます。ウィジェットが実行時に状態を変更できる場合、それはステートフルウィジェットになります。

2018年11月15日編集

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

一方、ステートフルウィジェットには内部状態があり、入力データが変更された場合、またはウィジェットの状態が変更された場合に再レンダリングできます。

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


新しいデータを外部からStatelessウィジェットに渡した後でも、実行時に変更することはできStatefulますが、ウィジェットとは呼ばれません(最後の行とは対照的です)。
CopsOnRoad 2018年

ステートレスウィジェットを「外部データが変更されたときに更新する」方法を説明していただけますか?(「外部データはコンストラクターを通過するデータ」です。)コンストラクターは一度だけ呼び出されるのではありませんか?コンストラクターを通過するデータはどのように変化しますか?
user1596274

8

非常に単純な例えが考えられます。あなたは本、装飾、そしてテレビを備えたいくつかの家具を持っています。家具はステートレスで、動かないものは何もありません。反対側のテレビでは、オン、オフ、チャンネルの変更、DVDが接続されている場合は映画の再生などができます。テレビには、動作に影響を与える内部状態があります。家具には状態がありません。家具の中のテレビの存在はそれに状態を追加していません。お役に立てれば。


これは、質問者の特定の質問に答えるものではありません。
イザヤ

1
これは素晴らしい例えです!
ウィリアムテリル

6

StackOverflowの質問への回答-ステートフルネスとステートレスネス

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

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

親ウィジェットは、子の状態を気にしないため、ステートレスです。ステートフルな子自体(または技術的にはFlutter)が自身の状態を処理します。
大まかに言えば、これにより親ウィジェットがステートフルになることに同意します。これは、2つの親に、状態の異なる2つの子が含まれている可能性があり、技術的に異なるためです。ただし、Flutterの観点からは、状態を気にせずに親ウィジェットを作成し、子を作成するときにのみ、状態の完全性を考慮します。


5

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

TL; DR:画面を更新できるウィジェットはステートフルウィジェットです。ステートレスではないウィジェット。

より詳細には、変更可能なコンテンツを含む動的ウィジェットはステートフルウィジェットである必要があります。ステートレスウィジェットは、パラメーターが変更された場合にのみコンテンツを変更できるため、ウィジェット階層内のその場所のポイントより上で実行する必要があります。静的コンテンツを含む画面またはウィジェットはステートレスウィジェットである必要がありますが、コンテンツを変更するには、ステートフルである必要があります。

私はこの相対的な内容を興味深い中程度の物語で見つけました。どういたしまして!


4

ステートレス:ウィジェットの状態は1回だけ作成され、値を更新できますが、明示的に状態を更新することはできません。これは、そこの構造からも明らかです。そのため、で拡張するクラスは1つだけStatelessWidgetです。したがって、私が言うと、build()メソッドを再度実行することはできません。

ステートフル:ウィジェットは、イベントがトリガーされると、STATE(ローカル)と値を複数回更新できます。それが理由で、実装も異なります。これには2つのクラスがあります。1つはStatefulWidgetState実装ハンドラー、つまりState<YourWidget>です。つまり、build()トリガーされたイベントに基づいて、メソッドを何度も再実行できます。

下の図が役に立ちます。

ここに画像の説明を入力してください


1

アプリを作成するときは、通常、StatelessWidgetまたはStatefulWidgetのいずれかのサブクラスである新しいウィジェットを作成します

ウィジェットStatelessWidgetStatefulWidgetウィジェットの違いは次のとおりです。

ステートレスウィジェット:

  1. 不変の状態を持つウィジェット。
  2. ステートレスウィジェットは静的ウィジェットです。
  3. これらは、データの変更や動作の変更に依存しません。
  4. ステートレスウィジェットには状態がありません。一度レンダリングされて更新されませんが、外部データが変更された場合にのみ更新されます。
  5. 例えば:TextIconRaisedButtonステートレスウィジェットです。

ステートレスウィジェット:

  1. 状態が変更可能なウィジェット。
  2. ステートフルウィジェットは動的ウィジェットです。
  3. これらは、ユーザーの操作またはデータの変更に基づいて、実行時に更新できます。
  4. ステートフルウィジェットには内部状態があり、入力データが変更された場合、またはウィジェットの状態が変更された場合に再レンダリングできます。
  5. 例えば:CheckboxRadio ButtonSliderステートフルウィジェットです

1

免責事項:-先週からフラッターの作業を開始しました:)

ステートレスウィジェットとステートフルウィジェットには、UIを作成および更新するための独自のライフサイクルがあります。ただし、ステートレスまたはステートフルのいずれかを使用してUIをレンダリングできますが、UIが外部データに完全にまたは部分的に依存している場合(たとえば、APIを使用してリストをレンダリングする場合)、ステートレスウィジェットを使用して静的UIをレンダリングする場合は、実際にはステートフルの方が便利です。良い習慣です。


1
・D:私は、著者は反対の意味を考える
ロクBoronat

0

簡単に言えば:

私たちが知っているように、すべてのウィジェットはフラッターのビューです。独自のクラスがあります。これらのクラスを使用すると、そのオブジェクトが作成されます。さまざまな変数/プロパティに値を与えます。例 文字列、色、フォントサイズ、フォントファミリを指定できるように、テキストウィジェットを作成しています。したがって、これを与えることにより、作成中にそのプロパティを定義しています。この時点まで、ステートレスウィジェットとステートフルウィジェットは同じですが、

そのプロパティ(たとえば、文字列または色)を後で何度も変更/更新する場合は、ステートフルウィジェットにする必要があります。

そして、最初に定義した後でそのプロパティを変更したくない場合は、ステートレスウィジェットです。

つまり、ウィジェットが保持/制御/表示するデータに関心があるということです。

つまり、ステートレスはデータが少なく、ステートフルはデータがいっぱいです。

ここで、ステートレスのクラスを定義すると、このクラスは変数を気にしない/持っていないか、独自のクラス、つまりクラスレベルでデータを言うが、データを気にする別のウィジェット/クラスを持っている可能性があります。つまり、ステートフルです。 。したがって、相互に影響はありません。

ここで間違っている場合は訂正してください。


0

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

ステートレスウィジェット:ステートレスウィジェットは、親が変更された場合にのみビルドされます。

ステートフルウィジェット:状態フルウィジェットはウィジェットの状態を保持し、状態が変化したときに再構築できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.