末尾または最初にsuper.initStateを呼び出す必要がありますか?


10

super.initSate()インフラッターをどこに呼び出すかについて混乱していますか?一部のコード例では、最初と最後に呼び出されます。違いはありますか?

私はこれをグーグルしようとしましたが、この関数呼び出しの位置に関する説明は見つかりませんでした。

どちらが正しいか?

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

または

void initState() {    
  //DO OTHER STUFF
  super.initState();    
}

回答:


4

それはmixinsのために重要です(そしてあなたのためにもそのため

でライフサイクルメソッドをオーバーライドするときにスーパーメソッドを呼び出すことは、FlutterフレームワークのパラダイムStateです。でも、なぜこれがあるdeactivate持っているmustCallSuper注釈を
さらに、一部mixinのユーザーは、関数の特定のポイントでこれらのライフサイクルメソッドのスーパーメソッドを呼び出すことを期待しています。

これは、フレームワークのs がこれに該当すると想定しているため、ドキュメントに従ってメソッドsuper.dispose の最後で呼び出す必要があることを意味します。 たとえば、次のようにしてアサート終わりに:disposemixinState
TickerProviderStateMixinSingleTickerProviderStateMixin super.dispose

すべてのティッカーは、super.dispose()を呼び出す前に破棄する必要があります。

別の例:およびでAutomaticKeepAliveMixinロジックを実行initStatedisposeます。

結論

開始あなたinitStatesuper.initStateし、あなたを終了するdisposesuper.dispose、追加簡単で安全側になりたい場合はmixin、あなたに秒State
さらに、Stateフレームワークはドキュメントで説明されているスーパーメソッドを呼び出すことを想定しているため、他のライフサイクルメソッド(で上書きするメソッド)のドキュメントに従ってください。

したがって、次のことを行う必要があります。

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

ただし、これは本当に重要ではありませState。これについては、以下で説明しますが、ミックスインについても同様です。重要なのは、私が見つけたものから判断するアサーションだけです。したがって、本番アプリには影響しません。

それは問題ではありません State

Pablo BarreraCopsOnRoadからの前の2つの答えは誤解を招くものだと思います。問題の真実はそれは本当に問題ではなく、遠くを見る必要がないためです。

アクションのみsuper.initStatesuper.disposeに取るStateクラスは、それ自体があるアサーションとするのでassert-statementsのみで評価されているデバッグモード、それが生産モードでは、すなわち、すべてのビルド一度のアプリでは問題ではありません。


以下では、私が何をご案内しますsuper.initStateし、super.dispose中に行うStateあなたは追加のミックスインを持っていないときに実行されるすべてのコードです。

initState

super.initState最初に実行されるコードを正確に見てみましょう(ソース):

@protected
@mustCallSuper
void initState() {
  assert(_debugLifecycleState == _StateLifecycle.created);
}

ご覧のとおり、ライフサイクルアサーションしかありません。その目的は、ウィジェットが正しく動作することを確認することです。だから、限り、あなたが呼び出すとsuper.initState 、どこか自分自身ではinitState、次のように表示されますAssertionError意図したとおりに、あなたのウィジェットが動作しない場合。これはassert、コード内の何かがとにかく間違っていることを報告するだけsuper.initStateであり、メソッドの最後で呼び出したとしてもそれがわかるため、事前に何らかのアクションをとったかどうかは関係ありません。

dispose

disposeこの方法は、(類似しているソース)。

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

ご覧のように、デバッグライフサイクルチェックを処理するアサーションのみが含まれています。ここで2番目assertは、_debugLifecycleStateデバッグモードでのみ変更されることが保証されるため、素晴らしいトリックです(- assertステートメントはデバッグモードでのみ実行されるため)。
つまり、独自のメソッドのsuper.dispose どこかで呼び出しを行う限り、追加機能を追加するミックスインなしで値を失うことはありません。


1
Flutterの公式ドキュメントはあまり良くありません:(回答ありがとう
ござい

説明してくれてありがとう、説明してもよろしいですか?initState()メソッドには1行しかassert(...)ないのでsuper.initState()、製品版アプリを呼び出すことの利点は何ですか?
CopsOnRoad

1
ありがとう。今では理にかなっています!だから私はより安全な側にいると思います、そして良いプログラミングの実践のために、それをコードの最初に置いておくことは良いことです。
K Vij

@creativecreatorormaybenotつまり、FlutterチームはmustCallSuper、Flutterが誕生してから2年以上の間、その方法を採用することで頭を悩ませています。それをそこに置くことの利点は何ですか?
CopsOnRoad

@creativecreatorormaybenotチームがのためmixinに作成した場合でも、これinitStateには1つのステートメントがあります。つまり、本番環境のアプリをassert(...)呼び出すことの重要性は何super.initState()ですか?
CopsOnRoad

3

super.initState()常にinitStateメソッドの最初の行にする必要があります。

ドキュメントから:

initState():これをオーバーライドする場合は、メソッドが必ずsuper.initState()の呼び出しで始まるようにしてください。


2

フレームワークのクラスでわかるように、ウィジェットが初期化された後、つまりの後をすべて実行する必要がありますsuper.initState()

私が処分する場合は、論理的には逆になりますsuper.dispose()。最初にすべてを実行してから、を呼び出します。

@override
void initState() {
  super.initState();
  // DO STUFF
}

@override
void dispose() {
  // DO STUFF
  super.dispose();
}

THX。しかし、私はいくつかのコード例でそれに気づきました。initStateメソッドの最後に呼び出されます...
K Vij

それは私が言ったことだ
パブロ・バレラ

0

initStateは、新しいステートフルウィジェットがウィジェットツリーに追加されるたびにデフォルトで呼び出されます。これで、super.initStateがウィジェットの基本クラスのデフォルト実装を実行します。基本クラスに依存するsuper.initStateの前に何かを呼び出すと、問題が発生する可能性があります。そのため、次の方法でinitStateを呼び出すことをお勧めします。

@override
void initState() {
  super.initState();
  // DO STUFF
}

disposeそれは反対なので、推論は少し欠陥があります。フレームワークはsuper.dispose 、最後に呼び出すことを期待していますが、推奨事項は正しいです。
creativecreatoror19年

他のものを破棄する前にsuper.disposeを呼び出すと、基本クラスに依存するコンポーネントが競合する可能性があるためです。
Anirudh Sharma
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.