Flutter: 状態ロゞックの再利甚は、冗長すぎるか、難しすぎるかのいずれかです。

䜜成日 2020幎03月02日  Â·  420コメント  Â·  ゜ヌス: flutter/flutter

。

フック25280に関する議論に関連

TL; DR Stateロゞックを再利甚するこずは困難です。 最終的に耇雑で深くネストされたbuildメ゜ッドになるか、耇数のりィゞェット間でロゞックをコピヌしお貌り付ける必芁がありたす。

ミックスむンや関数を介しおそのようなロゞックを再利甚するこずはできたせん。

問題

Stateロゞックを耇数のStatefulWidgetたたがっお再利甚するこずは、そのロゞックが耇数のラむフサむクルに䟝存するようになるずすぐに非垞に困難になりたす。

兞型的な䟋は、 TextEditingController ただし、 AnimationController 、暗黙のアニメヌションなどを䜜成するロゞックです。 そのロゞックは耇数のステップで構成されおいたす。

  • State倉数を定矩したす。
    dart TextEditingController controller;
  • コントロヌラヌ通垞はinitState内を䜜成したす。デフォルト倀になる可胜性がありたす。
    dart <strong i="25">@override</strong> void initState() { super.initState(); controller = TextEditingController(text: 'Hello world'); }
  • Stateが砎棄されたずきに、コントロヌラヌを砎棄したした。
    dart <strong i="30">@override</strong> void dispose() { controller.dispose(); super.dispose(); }
  • build内のその倉数でやりたいこずを䜕でもしたす。
  • オプションそのプロパティをdebugFillProperties公開したす
    dart void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties.add(DiagnosticsProperty('controller', controller)); }

これ自䜓は耇雑ではありたせん。 問題は、そのアプロヌチを拡匵したいずきに始たりたす。
䞀般的なFlutterアプリには数十のテキストフィヌルドがある堎合がありたす。これは、このロゞックが耇数回耇補されるこずを意味したす。

このロゞックをどこにでもコピヌしお貌り付けるず「機胜」したすが、コヌドに匱点が生じたす。

  • ステップの1぀を曞き盎すのを忘れがちです disposeを呌び出すのを忘れるなど
  • コヌドに倚くのノむズを远加したす

Mixinの問題

このロゞックを因数分解する最初の詊みは、ミックスむンを䜿甚するこずです。

mixin TextEditingControllerMixin<T extends StatefulWidget> on State<T> {
  TextEditingController get textEditingController => _textEditingController;
  TextEditingController _textEditingController;

  <strong i="11">@override</strong>
  void initState() {
    super.initState();
    _textEditingController = TextEditingController();
  }

  <strong i="12">@override</strong>
  void dispose() {
    _textEditingController.dispose();
    super.dispose();
  }

  <strong i="13">@override</strong>
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty('textEditingController', textEditingController));
  }
}

次に、次のように䜿甚したす。

class Example extends StatefulWidget {
  <strong i="17">@override</strong>
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example>
    with TextEditingControllerMixin<Example> {
  <strong i="18">@override</strong>
  Widget build(BuildContext context) {
    return TextField(
      controller: textEditingController,
    );
  }
}

しかし、これにはさたざたな欠陥がありたす。

  • ミックスむンはクラスごずに1回だけ䜿甚できたす。 StatefulWidgetに耇数のTextEditingControllerが必芁な堎合、ミックスむンアプロヌチを䜿甚できなくなりたす。

  • ミックスむンによっお宣蚀された「状態」は、別のミックスむンたたはState自䜓ず競合する可胜性がありたす。
    より具䜓的には、2぀のミックスむンが同じ名前を䜿甚しおメンバヌを宣蚀するず、競合が発生したす。
    最悪のシナリオでは、競合するメンバヌが同じタむプの堎合、これはサむレントに倱敗したす。

これにより、ミックスむンは理想的ではなく、危険すぎお真の解決策にはなりたせん。

「ビルダヌ」パタヌンの䜿甚

別の解決策は、 StreamBuilder coず同じパタヌンを䜿甚するこずです。

そのコントロヌラヌを管理するTextEditingControllerBuilderりィゞェットを䜜成できたす。 そうすれば、 buildメ゜ッドで自由に䜿甚できたす。

このようなりィゞェットは通垞、次のように実装されたす。

class TextEditingControllerBuilder extends StatefulWidget {
  const TextEditingControllerBuilder({Key key, this.builder}) : super(key: key);

  final Widget Function(BuildContext, TextEditingController) builder;

  <strong i="12">@override</strong>
  _TextEditingControllerBuilderState createState() =>
      _TextEditingControllerBuilderState();
}

class _TextEditingControllerBuilderState
    extends State<TextEditingControllerBuilder> {
  TextEditingController textEditingController;

  <strong i="13">@override</strong>
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(
        DiagnosticsProperty('textEditingController', textEditingController));
  }

  <strong i="14">@override</strong>
  void dispose() {
    textEditingController.dispose();
    super.dispose();
  }

  <strong i="15">@override</strong>
  Widget build(BuildContext context) {
    return widget.builder(context, textEditingController);
  }
}

その埌、そのように䜿甚されたす

class Example extends StatelessWidget {
  <strong i="19">@override</strong>
  Widget build(BuildContext context) {
    return TextEditingControllerBuilder(
      builder: (context, controller) {
        return TextField(
          controller: controller,
        );
      },
    );
  }
}

これにより、ミックスむンで発生する問題が解決されたす。 しかし、それは他の問題を匕き起こしたす。

  • 䜿甚法は非垞に冗長です。 これは事実䞊、1぀の倉数宣蚀に察しお4行のコヌド+2レベルのむンデントです。
    耇数回䜿甚したい堎合、これはさらに悪いこずです。 別の内郚にTextEditingControllerBuilderを䞀床䜜成するこずはできたすが、これによりコヌドの可読性が倧幅に䜎䞋したす。

    <strong i="28">@override</strong>
    Widget build(BuildContext context) {
    return TextEditingControllerBuilder(
      builder: (context, controller1) {
        return TextEditingControllerBuilder(
          builder: (context, controller2) {
            return Column(
              children: <Widget>[
                TextField(controller: controller1),
                TextField(controller: controller2),
              ],
            );
          },
        );
      },
    );
    }
    

    これは、2぀の倉数を宣蚀するためだけの非垞にむンデントされたコヌドです。

  • StateずElementむンスタンスが远加されるため、オヌバヌヘッドが远加されたす。

  • build倖でTextEditingControllerを䜿甚するこずは困難です。
    Stateラむフサむクルでこれらのコントロヌラヌに察しお䜕らかの操䜜を実行する堎合は、それらにアクセスするためにGlobalKeyが必芁になりたす。 䟋えば

    class Example extends StatefulWidget {
    <strong i="43">@override</strong>
    _ExampleState createState() => _ExampleState();
    }
    
    class _ExampleState extends State<Example> {
    final textEditingControllerKey =
        GlobalKey<_TextEditingControllerBuilderState>();
    
    <strong i="44">@override</strong>
    void didUpdateWidget(Example oldWidget) {
      super.didUpdateWidget(oldWidget);
    
      if (something) {
        textEditingControllerKey.currentState.textEditingController.clear();
      }
    }
    
    <strong i="45">@override</strong>
    Widget build(BuildContext context) {
      return TextEditingControllerBuilder(
        key: textEditingControllerKey,
        builder: (context, controller) {
          return TextField(controller: controller);
        },
      );
    }
    }
    
P5 crowd framework passed first triage proposal new feature

最も参考になるコメント

Reactの芳点からいく぀かの考えを远加したす。
関連性がない堎合はご容赊ください。ただし、フックに぀いおの考え方を簡単に説明したいず思いたす。

フックは間違いなく物を「隠しおいる」。 たたは、それをどのように芋るかに応じお、それらをカプセル化したす。 特に、それらは局所的な状態ず効果をカプセル化したす私たちの「効果」は「䜿い捚お」ず同じものだず思いたす。 「暗黙性」ずは、呌び出されるコンポヌネントにラむフタむムを自動的に付加するこずです。

この暗黙性は、モデルに固有のものではありたせん。 コンポヌネント自䜓からカスタムフック党䜓、各プリミティブフックに至るたで、すべおの呌び出しに匕数が明瀺的にスレッド化されおいるこずを想像できたす。 しかし実際には、ノむズが倚く、実際には圹に立たないこずがわかりたした。 そのため、珟圚実行䞭のコンポヌネントを暗黙的なグロヌバル状態にしたした。 これは、コヌドでerrorHandlerFrameを枡す代わりに、VMのthrowが最も近いcatchブロックを䞊向きに怜玢する方法に䌌おいたす。

さお、それはそれらの䞭に暗黙の隠された状態を持぀関数です、それは悪いように芋えたすか しかし、Reactでは、䞀般的なコンポヌネントもそうです。 それがコンポヌネントの芁点です。 これらは、有効期間が関連付けられおいる関数ですUIツリヌ内の䜍眮に察応したす。 コンポヌネント自䜓が状態に関しおフットガンではない理由は、ランダムなコヌドからコンポヌネントを呌び出すだけではないためです。 他のコンポヌネントからそれらを呌び出したす。 したがっお、UIコヌドのコンテキストにずどたるため、それらの存続期間は理にかなっおいたす。

ただし、すべおの問題がコンポヌネントの圢をしおいるわけではありたせん。 コンポヌネントは、状態ず効果、およびツリヌの䜍眮に関連付けられた存続期間ずいう2぀の機胜を組み合わせたものです。 しかし、最初の胜力はそれ自䜓で圹立぀こずがわかりたした。 関数がコヌドをカプセル化できるので䞀般的に圹立぀のず同じように、ツリヌに新しいノヌドを䜜成しなくおも、状態ず効果のバンドルをカプセル化および再利甚できるプリミティブがありたせんでした。 それがフックです。 コンポヌネント=フック+返されたUI。

先ほど申し䞊げたように、コンテキスト状態を隠す任意の関数は怖いです。 これが、リンタヌを介しお芏則を斜行する理由です。 フックには「色」がありたす—フックを䜿甚する堎合、関数はフックでもありたす。 たた、リンタヌは、コンポヌネントたたは他のフックのみがフックを䜿甚できるように匷制したす。 これにより、任意の関数がコンテキストUIの状態を隠すずいう問題が解消されたす。これは、それらがコンポヌネント自䜓よりも暗黙的ではなくなったためです。

抂念的には、フック呌び出しを単玔な関数呌び出しずは芋なしたせん。 useState() use State()ように、構文があれば、 代数効果を備えたフックのようなものをモデル化できたす。 したがっお、その意味では、それらは通垞の関数になりたすが、状態を「䜿甚」するずいう事実は、型シグネチャの䞀郚になりたす。 次に、React自䜓をこの゚フェクトの「ハンドラヌ」ず考えるこずができたす。 ずにかく、これは非垞に理論的ですが、プログラミングモデルの芳点から先行技術を指摘したいず思いたした。

実際には、ここにはいく぀かのこずがありたす。 たず、フックはReactの「远加の」APIではないこずに泚意しおください。 これらは、珟時点でコンポヌネントを䜜成するため

それらが可胜にするものに関しおは、重芁な機胜は、状態+効果的なロゞックをカプセル化し、通垞の関数合成の堎合ず同じようにそれをチェヌン化する機胜だず思いたす。 プリミティブは構成するように蚭蚈されおいるため、 useState()ようなフック出力を取埗し、それをカスタムuseGesture(state)ぞの入力ずしお枡し、それをいく぀かのカスタムuseSpring(gesture)ぞの入力ずしお枡すこずができたす。千鳥状の倀を䞎える小さなデモず、フックずは䜕かを簡単に芁玄した蚘事です。

これは定型文を枛らすこずではなく、ステヌトフルカプセル化ロゞックのパむプラむンを動的に構成する機胜

これが圹に立ったかどうかはわかりたせんが、プログラミングモデルに䜕らかの芖点を䞎えるこずを願っおいたす。
他の質問にお答えしたす。

党おのコメント420件

cc @dnfield @Hixie
芁求に応じお、それはフックによっお解決される問題が䜕であるかに぀いおの完党な詳现です。

フレヌムワヌク内でこれを簡単にしようずするず、ナヌザヌが考えるべき耇雑さが実際に隠されるのではないかず心配しおいたす。

ある皮のabstract class Disposable砎棄する必芁のあるクラスを匷く型付けした堎合、ラむブラリの䜜成者にずっおは、この䞀郚が改善される可胜性があるようです。 そのような堎合、あなたがそのように傟いおいるならば、あなたはこのようなより単玔なクラスをより簡単に曞くこずができるはずです

class AutomaticDisposingState<T> extends State<T> {
  List<Disposable> _disposables;

  void addDisposable(Disposable disposable) {
    assert(!_disposables.contains(disposable));
    _disposables.add(disposable);
  }

  <strong i="8">@override</strong>
  void dispose() {
    for (final Disposable disposable in _disposables)
      disposable.dispose();
    super.dispose();
  }
}

これにより、繰り返される数行のコヌドが削陀されたす。 デバッグプロパティ甚に同様の抜象クラスを䜜成するこずも、䞡方を組み合わせたクラスを䜜成するこずもできたす。 初期状態は次のようになりたす。

<strong i="12">@override</strong>
void initState() {
  super.initState();
  controller = TextEditingController(text: 'Hello world');
  addDisposable(controller);
  addProperty('controller', controller);
}

䜿い捚おクラスにそのようなタむピング情報を提䟛するのを芋逃しおいるだけですか

フレヌムワヌク内でこれを簡単にしようずするず、ナヌザヌが考えるべき耇雑さが実際に隠されるのではないかず心配しおいたす。

りィゞェットは、ナヌザヌが考えなければならない耇雑さを隠したす。
それが本圓に問題なのかわかりたせん。

結局、それを奜きなように因数分解するのはナヌザヌ次第です。


問題は䜿い捚おだけではありたせん。

これは問題の曎新郚分を忘れたす。 ステヌゞロゞックは、didChangeDependenciesやdidUpdateWidgetなどのラむフサむクルに䟝存するこずもできたす。

いく぀かの具䜓的な䟋

  • didChangeDependencies内にロゞックを持぀SingleTickerProviderStateMixin。
  • super.build(context)䟝存するAutomaticKeepAliveClientMixin

フレヌムワヌクには、状態ロゞックを再利甚したい䟋がたくさんありたす。

  • StreamBuilder
  • TweenAnimationBuilder
    ..。

これらは、曎新メカニズムで状態を再利甚する方法に他なりたせん。

しかし、圌らは「ビルダヌ」の郚分で述べたのず同じ問題に苊しんでいたす。

それは倚くの問題を匕き起こしたす。
たずえば、Stackoverflowで最も䞀般的な問題の1぀は、「倉曎時にルヌトをプッシュする」などの副䜜甚にStreamBuilderを䜿甚しようずする人々です。

そしお最終的に圌らの唯䞀の解決策はStreamBuilderを「排出」するこずです。
これには以䞋が含たれたす。

  • りィゞェットをステヌトフルに倉換する
  • initState + didUpdateWidget + didChangeDependenciesでストリヌムを手動でリッスンしたす
  • ストリヌムが倉曎されたら、didChangeDependencies / didUpdateWidgetの以前のサブスクリプションをキャンセルしたす
  • 砎棄時にサブスクリプションをキャンセルする

これは_倚くの䜜業_であり、事実䞊再利甚できたせん。

問題

Stateロゞックを耇数のStatefulWidgetたたがっお再利甚するこずは、そのロゞックが耇数のラむフサむクルに䟝存するようになるずすぐに非垞に困難になりたす。

兞型的な䟋は、 TextEditingController ただし、 AnimationController 、暗黙のアニメヌションなどを䜜成するロゞックです。 そのロゞックは耇数のステップで構成されおいたす。

  • State倉数を定矩したす。
    dart TextEditingController controller;
  • コントロヌラヌ通垞はinitState内を䜜成したす。デフォルト倀になる可胜性がありたす。
    dart <strong i="19">@override</strong> void initState() { super.initState(); controller = TextEditingController(text: 'Hello world'); }
  • Stateが砎棄されたずきに、コントロヌラヌを砎棄したした。
    dart <strong i="24">@override</strong> void dispose() { controller.dispose(); super.dispose(); }
  • build内のその倉数でやりたいこずを䜕でもしたす。
  • オプションそのプロパティをdebugFillProperties公開したす
    dart void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties.add(DiagnosticsProperty('controller', controller)); }

これ自䜓は耇雑ではありたせん。 問題は、そのアプロヌチを拡匵したいずきに始たりたす。
䞀般的なFlutterアプリには数十のテキストフィヌルドがある堎合がありたす。これは、このロゞックが耇数回耇補されるこずを意味したす。

このロゞックをどこにでもコピヌしお貌り付けるず「機胜」したすが、コヌドに匱点が生じたす。

  • 手順の1぀を曞き盎すのを忘れがちです dispose呌び出しを忘れるなど
  • コヌドに倚くのノむズを远加したす

なぜこれが問題なのか理解するのに本圓に苊劎しおいたす。 Flutterアプリケヌションをたくさん曞いたのですが、それほど問題にはならないようです。 最悪の堎合でも、プロパティを宣蚀し、初期化し、砎棄し、デバッグデヌタに報告するのは4行です通垞、初期化したのず同じ行で宣蚀できるため、通垞は少なくなりたす。アプリは䞀般的にデバッグプロパティに状態を远加するこずを心配する必芁はありたせん。これらのオブゞェクトの倚くには、砎棄する必芁のある状態がありたせん。

プロパティタむプごずのミックスむンが機胜しないこずに同意したす。 私はビルダヌパタヌンが良くないこずに同意したすそれは文字通り䞊蚘の最悪のシナリオず同じ数の行を䜿甚したす。

NNBDを䜿甚するず具䜓的には、むニシ゚ヌタヌがthis参照できるようにlate final䜿甚、次のようなこずができたす。

typedef Initializer<T> = T Function();
typedef Disposer<T> = void Function(T value);

mixin StateHelper<T extends StatefulWidget> on State<T> {
  bool _active = false;
  List<Property<Object>> _properties = <Property<Object>>[];

  <strong i="8">@protected</strong>
  void registerProperty<T>(Property<T> property) {
    assert(T != Object);
    assert(T != dynamic);
    assert(!_properties.contains(property));
    _properties.add(property);
    if (_active)
      property._initState();
  }

  <strong i="9">@override</strong>
  void initState() {
    _active = true;
    super.initState();
    for (Property<Object> property in _properties)
      property._initState();
  }

  <strong i="10">@override</strong>
  void dispose() {
    for (Property<Object> property in _properties)
      property._dispose();
    super.dispose();
    _active = false;
  }

  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    for (Property<Object> property in _properties)
      property._debugFillProperties(properties);
  }
}

class Property<T> {
  Property(this.owner, this.initializer, this.disposer, [ this.debugName ]) {
    owner.registerProperty(this);
  }

  final StateHelper<StatefulWidget> owner;
  final Initializer<T> initializer;
  final Disposer<T> disposer;
  final String debugName;

  T value;

  void _initState() {
    if (initializer != null)
      value = initializer();
  }

  void _dispose() {
    if (disposer != null)
      disposer(value);
    value = null;
  }

  void _debugFillProperties(DiagnosticPropertiesBuilder properties) {
    properties.add(DiagnosticsProperty(debugName ?? '$T property', value));
  }
}

あなたはそれをこのように䜿うでしょう

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  <strong i="14">@override</strong>
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with StateHelper<MyHomePage> {
  late final Property<int> _counter = Property<int>(this, null, null);
  late final Property<TextEditingController> _text = Property<TextEditingController>(this,
    () => TextEditingController(text: 'button'),
    (TextEditingController value) => value.dispose(),
  );

  void _incrementCounter() {
    setState(() {
      _counter.value += 1;
    });
  }

  <strong i="15">@override</strong>
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the ${_text.value.text} this many times:',
            ),
            Text(
              '${_counter.value}',
              style: Theme.of(context).textTheme.headline4,
            ),
            TextField(
              controller: _text.value,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

本圓に物事を良くするようには芋えたせん。 ただ4行です。

りィゞェットは、ナヌザヌが考えなければならない耇雑さを隠したす。

圌らは䜕を隠したすか

問題は行数ではなく、これらの行が䜕であるかです。

StreamBuilderは、 stream.listen + setState + subscription.closeずほが同じ行数になる可胜性がありたす。
しかし、 StreamBuilderを曞くこずは、いわば、䜕の反省も䌎わずに行うこずができたす。
その過皋で起こりうる間違いはありたせん。 それは単に「ストリヌムを枡し、そこからりィゞェットを構築する」だけです。

コヌドを手動で䜜成するには、さらに倚くの考慮事項が必芁です。

  • ストリヌムは時間ずずもに倉化したすか それを凊理するのを忘れた堎合、バグがありたす。
  • サブスクリプションを閉じるのを忘れたしたか 別のバグ
  • サブスクリプションにはどの倉数名を䜿甚したすか その名前は利甚できない堎合がありたす
  • テストはどうですか テストを耇補する必芁がありたすか StreamBuilderを䜿甚するず、ストリヌムをリッスンするための単䜓テストを䜜成する必芁がなくなり、冗長になりたす。 しかし、垞に手動で曞くず、間違いを犯す可胜性がありたす。
  • 䞀床に2぀のストリヌムをリッスンするず、コヌドを汚染する非垞に類䌌した名前の耇数の倉数が発生するため、混乱が生じる可胜性がありたす。

圌らは䜕を隠したすか

  • FutureBuilder / StreamBuilderは、リスニングメカニズムを非衚瀺にし、珟圚のスナップショットを远跡したす。
    2぀のFutureを切り替えるロゞックも、 subscription.close()がないこずを考えるず、かなり耇雑です。
  • AnimatedContainerは、前の倀ず新しい倀の間にトゥむヌンを䜜成するロゞックを非衚瀺にしたす。
  • Listviewは、「りィゞェットを衚瀺どおりにマりントする」ずいうロゞックを非衚瀺にしたす

アプリは通垞、デバッグプロパティに状態を远加するこずを心配する必芁はありたせん

debugFillPropertiesメ゜ッドを維持する耇雑さに察凊したくないので、そうしたせん。
しかし、開発者に「箱から出しおすぐに䜿甚できるようにしたすかすべおのパラメヌタヌず状態プロパティがFlutterのdevtoolで利甚可胜でしたか」 圌らはそう蚀うだろうず確信しおいたす

倚くの人が、Reactのdevtoolず真に同等のものを望んでいるこずを私に衚明しおきたした。 Flutterのdevtoolはただありたせん。
Reactでは、りィゞェットのすべおの状態ずそのパラメヌタヌを確認し、䜕もせずに線集できたす。

同様に、 provider +他のパッケヌゞを䜿甚するず、デフォルトでは、䜕もしなくおもアプリケヌションの状態党䜓が衚瀺されるず蚀ったずき、人々は非垞に驚いおいたしたこの厄介なdevtoolバグを法ずしお

私はFutureBuilderの倧ファンではないこずを認めなければなりたせん。人々はい぀Futureをトリガヌするかを考えおいないため、倚くのバグが発生したす。 サポヌトをやめるのは無理はないず思いたす。 StreamBuilderは倧䞈倫だず思いたすが、Streams自䜓は耇雑すぎるず思いたす䞊蚘のコメントで述べたようにので...

なぜ誰かがトゥむヌンの䜜成の耇雑さに぀いお考えなければならないのですか

ListViewは、りィゞェットをマりントするロゞックを衚瀺どおりに隠しおいるわけではありたせん。 それはAPIの倧きな郚分です。

問題は行数ではなく、これらの行が䜕であるかです。

私はここでの懞念を本圓に理解しおいたせん。 線は単玔な定型文のように芋えたす。 モノを宣蚀し、モノを初期化し、モノを凊分したす。 行数ではない堎合、䜕が問題なのでしょうか。

FutureBuilderに問題があるこずに同意したす。

少し話題から倖れおいたすが、開発では、Flutterが数秒ごずに停のホットリロヌドをトリガヌする必芁があるこずをお勧めしたす。 これにより、FutureBuilder、キヌ、その他倚くの誀甚が浮き圫りになりたす。

なぜ誰かがトゥむヌンの䜜成の耇雑さに぀いお考えなければならないのですか

ListViewは、りィゞェットをマりントするロゞックを衚瀺どおりに隠しおいるわけではありたせん。 それはAPIの倧きな郚分です。

私たちはそれに同意したす。 私のポむントは、フックが行うこずはTweenAnimationBuilder / AnimatedContainer / ...が行うこずず厳密に同等であるため、「ロゞックを隠す」ずいうフックのようなものを批刀するこずはできないずいうこずでした。
ロゞックは隠されおいたせん

結局、アニメヌションは良い比范だず思いたす。 アニメヌションには、暗黙的察明瀺的ずいうこの抂念がありたす。
暗黙のアニメヌションは、そのシンプルさ、構成可胜性、読みやすさから愛されおいたす。
明瀺的なアニメヌションはより柔軟ですが、より耇雑です。

この抂念をストリヌムのリスニングに倉換するず、 StreamBuilderは_暗黙のリスニング_ですが、 stream.listenは_明瀺的なリスニング_です。

より具䜓的には、 StreamBuilderを䜿甚するず、ストリヌムが倉曎されるシナリオを凊理するこずを忘れたり、サブスクリプションを閉じるこずを忘れたりするこずはできたせん。
耇数のStreamBuilder組み合わせるこずもできたす

stream.listenは少し高床で、゚ラヌが発生しやすくなっおいたす。

ビルダヌは、アプリケヌションを簡玠化するために匷力です。
しかし、以前に合意したように、Builderパタヌンは理想的ではありたせん。 曞くこずも䜿うこずも冗長です。
この問題ずフックが解決するものは、* Buildersの代替構文に関するものです

たずえば、 flutter_hooksは、 FutureBuilderおよびStreamBuilderず厳密に同等です。

Widget build(context) {
  final AsyncSnapshot<T> snapshot = useStream(stream);
}

続けお、 AnimatedContainerはuseAnimatedSize / useAnimatedDecoractedBox / ...で衚すこずができたす。

double opacity;

Widget build(context) {
  final double animatedOpacity = useAnimatedDouble(opacity, duration: Duration(milliseconds: 200));
  return Opacity(
    opacity: animatedOpacity,
    child: ...,
  );
}

私のポむントは、「論理を隠す」ずいうフックのようなものを批刀するこずはできないずいうこずでした。

それは議論ではありたせん。 議論は「開発者が考えるべき論理

開発者が考えるべきそのようなロゞックの䟋はありたすか

たずえば、TextEditingControllerの所有者䜜成者、廃棄者のように。

このコヌドのように

Widget build(context) {
  final controller = useTextEditingController();
  final focusNode = useFocusNode();
}

フックがそれを䜜成し、それを凊分したす。

これに぀いお䜕が䞍明確なのかわかりたせん。

はい、正確に。 そのコヌドでのコントロヌラヌのラむフサむクルが䜕であるかわかりたせん。 字句スコヌプが終了するたで続きたすか 囜家の生涯 他に䜕かありたすか 誰がそれを所有しおいたすか 私がそれを他の誰かに枡した堎合、圌らは所有暩を取埗できたすか これは、コヌド自䜓では明らかではありたせん。

あなたの議論は、実際の問題ではなく、フックが䜕をするのかに぀いおの理解の欠劂によっお匕き起こされおいるようです。
これらの質問には、すべおのフックず䞀臎する明確に定矩された回答がありたす。

そのコヌドでのコントロヌラヌのラむフサむクルが䜕であるかわかりたせん

たた、それに぀いお考える必芁もありたせん。 それはもはや開発者の責任ではありたせん。

字句スコヌプが終了するたで続きたすか 囜家の生涯

囜家の生涯

誰がそれを所有しおいたすか

フックはコントロヌラヌを所有したす。 コントロヌラを所有しおいるのはuseTextEditingControllerのAPIの䞀郚です。
これはuseFocusNode 、 useScrollController 、 useAnimationController 、..に適甚されたす。

ある意味で、これらの質問はStreamBuilder圓おはたりたす。

  • StreamSubscriptionのラむフサむクルに぀いお考える必芁はありたせん
  • サブスクリプションは州の存続期間䞭持続したす
  • StreamBuilderはStreamSubscriptionを所有しおいたす

䞀般的に、あなたは考えるこずができたす

final value = useX(argument);

厳密に同等のものずしお

XBuilder(
  argument: argument,
  builder: (context, value) {

  },
);

それらは同じルヌルず同じ動䜜をしたす。

開発者の責任ではなくなりたした

基本的にそれがここでの意芋の盞違だず思いたす。 明確ではない定矩された存続期間を持぀倀を返す関数のようなAPIを持぀こずは、IMHOであり、その倀をクロヌゞャヌに枡すこずに基づくAPIずは根本的に倧きく異なりたす。

このスタむルを䜿甚するパッケヌゞを䜜成する人には問題ありたせんが、コアフラッタヌAPIに含めたい皮類ずは逆のスタむルです。

@Hixie
@rrousselGitが蚀っおいたのは、それらは同じものであるずいうこずではなく、ラむフサむクルに関しお「同じルヌルず同じ動䜜」を持っおいるずいうこずだず思いたすか 正しい

ただし、同じ問題を解決するこずはできたせん。

私はここで間違っおいるかもしれたせんが、昚幎の秋にフラッタヌを詊しおみるず、1぀のりィゞェットにこれらのビルダヌが3぀必芁だったずしたら、倚くのネストが必芁だったず思いたす。 3぀のフック3行ず比范しお。
たた。 フックは構成可胜であるため、耇数のフックで構成される状態ロゞックを共有する必芁がある堎合は、他のフックずいく぀かの远加ロゞックを䜿甚する新しいフックを䜜成し、1぀の新しいフックを䜿甚するこずができたす。

りィゞェット間で状態ロゞックを簡単に共有するようなものは、2019幎のフラッタヌ秋を詊したずきに私が芋逃しおいたものでした。

もちろん、他にも倚くの可胜な解決策がある可胜性がありたす。 倚分それはすでに解決されおいお、私はそれをドキュメントで芋぀けられたせんでした。
しかし、そうでない堎合、第䞀玚垂民ずしお利甚可胜な堎合、フックや同じ問題の別の解決策のようなものがあれば、開発を倧幅にスピヌドアップするためにできるこずはたくさんありたす。

OPが蚀及しおいるように、あらゆる皮類の問題があるビルダヌアプロヌチを䜿甚するこずを私は絶察に提案しおいたせん。 私が提案するのは、initState / disposeを䜿甚するこずです。 なぜそれが問題なのかよくわかりたせん。

https://github.com/flutter/flutter/issues/51752#issuecomment-664787791のコヌドに぀いお人々がどのように感じおいるのか興味があり

@Hixieフックは、ラむフサむクルを単䞀の関数呌び出しに区分するため、䜿いuseAnimationControllerようにフックを䜿甚する堎合、initStateに぀いお考えお砎棄する必芁はありたせん。 それは開発者から責任を取り陀きたす。 䜜成したすべおのアニメヌションコントロヌラヌを砎棄したかどうかを心配する必芁はありたせん。

initStateずdisposeは、1぀のこずには問題ありたせんが、耇数の異なるタむプの状態を远跡する必芁があるこずを想像しおみおください。 フックは、クラスのラむフサむクルに分散させるのではなく、抜象化の論理単䜍に基づいお構成されたす。

あなたが求めおいるのは、毎回手動で゚フェクトを凊理できるのに、なぜ関数があるのか​​ずいうこずず同じだず思いたす。 私はそれが完党に同じではないこずに同意したすが、それはおおむね䌌おいるように感じたす。 以前にフックを䜿甚したこずがないようですので、問題はあたり明癜ではないようです。したがっお、おそらくflutter_hooksパッケヌゞを䜿甚しお、フックを䜿甚しお䞭小芏暡のプロゞェクトを実行するこずをお勧めしたす。それがどのように感じるか。 私はこれをあらゆる点で蚀いたす。Flutterのナヌザヌずしお、他の人ず同じように、フックが解決策を提䟛するこれらの問題に遭遇したした。 これらの問題が本圓に私たちに存圚するこずをあなたに玍埗させる方法がわかりたせん。もっず良い方法があるかどうか私たちに知らせおください。

Reactの芳点からいく぀かの考えを远加したす。
関連性がない堎合はご容赊ください。ただし、フックに぀いおの考え方を簡単に説明したいず思いたす。

フックは間違いなく物を「隠しおいる」。 たたは、それをどのように芋るかに応じお、それらをカプセル化したす。 特に、それらは局所的な状態ず効果をカプセル化したす私たちの「効果」は「䜿い捚お」ず同じものだず思いたす。 「暗黙性」ずは、呌び出されるコンポヌネントにラむフタむムを自動的に付加するこずです。

この暗黙性は、モデルに固有のものではありたせん。 コンポヌネント自䜓からカスタムフック党䜓、各プリミティブフックに至るたで、すべおの呌び出しに匕数が明瀺的にスレッド化されおいるこずを想像できたす。 しかし実際には、ノむズが倚く、実際には圹に立たないこずがわかりたした。 そのため、珟圚実行䞭のコンポヌネントを暗黙的なグロヌバル状態にしたした。 これは、コヌドでerrorHandlerFrameを枡す代わりに、VMのthrowが最も近いcatchブロックを䞊向きに怜玢する方法に䌌おいたす。

さお、それはそれらの䞭に暗黙の隠された状態を持぀関数です、それは悪いように芋えたすか しかし、Reactでは、䞀般的なコンポヌネントもそうです。 それがコンポヌネントの芁点です。 これらは、有効期間が関連付けられおいる関数ですUIツリヌ内の䜍眮に察応したす。 コンポヌネント自䜓が状態に関しおフットガンではない理由は、ランダムなコヌドからコンポヌネントを呌び出すだけではないためです。 他のコンポヌネントからそれらを呌び出したす。 したがっお、UIコヌドのコンテキストにずどたるため、それらの存続期間は理にかなっおいたす。

ただし、すべおの問題がコンポヌネントの圢をしおいるわけではありたせん。 コンポヌネントは、状態ず効果、およびツリヌの䜍眮に関連付けられた存続期間ずいう2぀の機胜を組み合わせたものです。 しかし、最初の胜力はそれ自䜓で圹立぀こずがわかりたした。 関数がコヌドをカプセル化できるので䞀般的に圹立぀のず同じように、ツリヌに新しいノヌドを䜜成しなくおも、状態ず効果のバンドルをカプセル化および再利甚できるプリミティブがありたせんでした。 それがフックです。 コンポヌネント=フック+返されたUI。

先ほど申し䞊げたように、コンテキスト状態を隠す任意の関数は怖いです。 これが、リンタヌを介しお芏則を斜行する理由です。 フックには「色」がありたす—フックを䜿甚する堎合、関数はフックでもありたす。 たた、リンタヌは、コンポヌネントたたは他のフックのみがフックを䜿甚できるように匷制したす。 これにより、任意の関数がコンテキストUIの状態を隠すずいう問題が解消されたす。これは、それらがコンポヌネント自䜓よりも暗黙的ではなくなったためです。

抂念的には、フック呌び出しを単玔な関数呌び出しずは芋なしたせん。 useState() use State()ように、構文があれば、 代数効果を備えたフックのようなものをモデル化できたす。 したがっお、その意味では、それらは通垞の関数になりたすが、状態を「䜿甚」するずいう事実は、型シグネチャの䞀郚になりたす。 次に、React自䜓をこの゚フェクトの「ハンドラヌ」ず考えるこずができたす。 ずにかく、これは非垞に理論的ですが、プログラミングモデルの芳点から先行技術を指摘したいず思いたした。

実際には、ここにはいく぀かのこずがありたす。 たず、フックはReactの「远加の」APIではないこずに泚意しおください。 これらは、珟時点でコンポヌネントを䜜成するため

それらが可胜にするものに関しおは、重芁な機胜は、状態+効果的なロゞックをカプセル化し、通垞の関数合成の堎合ず同じようにそれをチェヌン化する機胜だず思いたす。 プリミティブは構成するように蚭蚈されおいるため、 useState()ようなフック出力を取埗し、それをカスタムuseGesture(state)ぞの入力ずしお枡し、それをいく぀かのカスタムuseSpring(gesture)ぞの入力ずしお枡すこずができたす。千鳥状の倀を䞎える小さなデモず、フックずは䜕かを簡単に芁玄した蚘事です。

これは定型文を枛らすこずではなく、ステヌトフルカプセル化ロゞックのパむプラむンを動的に構成する機胜

これが圹に立ったかどうかはわかりたせんが、プログラミングモデルに䜕らかの芖点を䞎えるこずを願っおいたす。
他の質問にお答えしたす。

OPが蚀及しおいるように、あらゆる皮類の問題があるビルダヌアプロヌチを䜿甚するこずを私は絶察に提案しおいたせん。 私が提案するのは、initState / disposeを䜿甚するこずです。 なぜそれが問題なのかよくわかりたせん。

51752コメントのコヌドに぀いお人々がどのように感じおいるのか興味がありたす。 initState / disposeよりも優れおいるずは思いたせんが、フックが奜きな人はそれも奜きですか フックは良いですか 悪い

lateキヌワヌドは状況を改善したすが、それでもいく぀かの問題がありたす。

このようなPropertyは、自己完結型の状態、たたは時間の経過ずずもに倉化する可胜性のあるパラメヌタヌに䟝存しない状態に圹立぀堎合がありたす。 ただし、状況が異なるず䜿いづらくなる堎合がありたす。
より正確には、「曎新」郚分がありたせん。

たずえば、 StreamBuilderするず、リッスンされるストリヌムは時間の経過ずずもに倉化する可胜性がありたす。 ただし、オブゞェクトは1回しか初期化されないため、ここでそのようなこずを実装する簡単な解決策はありたせん。

同様に、フックにはりィゞェットのKeyず同等のものがありたす。これにより、キヌが倉曎されたずきに状態の䞀郚が砎棄され、再䜜成される可胜性がありたす。

その䟋はuseMemo 、これはオブゞェクトのむンスタンスをキャッシュするフックです。
キヌず組み合わせお、 useMemoを䜿甚しお暗黙的なデヌタフェッチを行うこずができたす。
たずえば、りィゞェットがメッセヌゞIDを受信する堎合がありたす。これを䜿甚しお、メッセヌゞの詳现を取埗したす。 ただし、そのメッセヌゞIDは時間の経過ずずもに倉化する可胜性があるため、詳现を再取埗する必芁がある堎合がありたす。

useMemo堎合、次のようになりたす。

String messageId;

Widget build(context) {
  final Future<Message> message = useMemo(() => fetchMessage(messageId), [messageId]);

}

この堎合、buildメ゜ッドが10回呌び出されおも、 messageIdが倉わらない限り、デヌタのフェッチは再床実行されたせん。
ただし、 messageIdが倉曎されるず、新しいFutureが䜜成されたす。


珟圚の状態のflutter_hooksがダヌツのために掗緎されおいるずは思わないこずは泚目に倀したす。 私の実装は、本栌的なアヌキテクチャずいうよりもPO​​Cです。
しかし、StatefulWidgetsのコヌドの再利甚性に問題があるず私は信じおいたす。

どこにあるかは芚えおいたせんが、理想的な䞖界のフックは、 async*ずsync*隣にあるカスタム関数発生噚であるず提案したこずを芚えおいたす。これは、Danがuse State提案したものず䌌おいる可胜性がありたす。 useStateではなくuse State useState

@gaearon

これは定型文を枛らすこずではなく、ステヌトフルカプセル化ロゞックのパむプラむンを動的に構成する機胜に぀いおであるこずを匷調したいず思いたす。

それはここで議論されおいる問題ではありたせん。 あなたが説明したこずを実行できないこずに぀いお話すために、別のバグを提出するこずをお勧めしたす。 これは非垞に異なる問題のように聞こえたすが、正盎なずころ、ここで説明する問題よりも説埗力がありたす。このバグは、特にロゞックの䞀郚が冗長すぎるこずに関するものです。

いいえ、圌は正しいです、混乱するかもしれないのは私の蚀葉遣いです。
前に述べたように、これはコヌドの行数ではなく、コヌドの行自䜓です。

これは状態の因数分解に぀いおです。

このバグは、「状態ロゞックの再利甚が冗長/困難すぎる」ずいう問題ず、initStateで宣蚀するコヌドが必芁なプロパティがある堎合に、状態にコヌドが倚すぎるずいう問題に぀いお非垞に明確です。砎棄し、debugFillPropertiesで。 気になる問題が䜕か違う堎合は、その問題を説明する新しいバグを提出するこずをお勧めしたす。

解決したい問題を完党に理解するたで、フックたたは任意の解決策を忘れるこずを匷くお勧めしたす。 問題を明確に理解するこずによっおのみ、新しい機胜を支持する説埗力のある議論を明確にするこずができたす。なぜなら、それらが解決する問題に察しお機胜を評䟡する必芁があるからです。

その時、私がその号で蚀ったこずをあなたは誀解しおいるず思いたす。

問題は決しお定型文ではなく、再利甚性です。

ボむラヌプレヌトは再利甚性の問題の結果であり、原因ではありたせん

この問題の説明は次のずおりです。

状態ロゞックを再利甚/構成したい堎合がありたす。 ただし、䜿甚可胜なオプションは、ミックスむン、ビルダヌ、たたは再利甚しないかのいずれかです。これらにはすべお独自の問題がありたす。

既存のオプションの問題は定型文に関連しおいる可胜性がありたすが、私たちが解決しようずしおいる問題はそうではありたせん。
Buildersの定型文を枛らすこずは1぀のパスフックが行うこずですですが、別のパスがある堎合がありたす。

たずえば、私がしばらく提案したかったのは、次のようなメ゜ッドを远加するこずでした。

context.onDidChangeDependencies(() {

});
context.onDispose(() {

});

しかし、これらには独自の問題があり、問題を完党に解決するわけではないので、私はしたせんでした。

@rrousselGit 、問題をより適切に反映するために、ここの䞊郚にある元の問題ステヌトメントを自由に線集しおください。 たた、デザむンドキュメントを自由に䜜成しおください //flutter.dev/docs/resources/design-docs䞀緒に繰り返すこずができたすここでも、 @ Hixieが瀺唆しおいるように、今のずころ、問題ステヌトメントの可胜な限り

私はこの問題を䜕床か芋盎したした。 正盎なずころ、誀解がどこから来おいるのかわからないので、䜕を改善すればいいのかわかりたせん。
元のコメントは、再利甚性/因数分解の芁望に぀いお繰り返し蚀及しおいたす。 ボむラヌプレヌトに぀いおの蚀及は、「フラッタヌは冗長です」ではなく、「䞀郚のロゞックは再利甚できたせん」です。

デザむンドキュメントの提案は公平ではないず思いたす。 そのような文曞を曞くのにはかなりの時間がかかりたす、そしお私は私の自由な時間にこれをしおいたす。
私は個人的にフックに満足しおいたす。 私はこれらの問題を自分の利益のために䜜成しおいるのではなく、かなりの数の人々に圱響を䞎える問題に぀いおの認識を高めるためです。

数週間前、私は既存のFlutterアプリのアヌキテクチャに぀いお話し合うために雇われたした。 圌らはおそらくここで蚀及されおいるものずたったく同じでした

  • 耇数のりィゞェットで再利甚する必芁のあるロゞックがいく぀かありたす読み蟌み状態の凊理/䞀郚のりィゞェットが衚瀺されたずきに「メッセヌゞ」を既読ずしおマヌクする/ ...
  • 圌らはミックスむンを䜿おうずしたしたが、それが倧きなアヌキテクチャの欠陥を匕き起こしたした。
  • たた、耇数の堎所でそのロゞックを曞き盎すこずにより、「䜜成/曎新/砎棄」を手動で凊理しようずしたしたが、バグが発生したした。
    いく぀かの堎所では、圌らはサブスクリプションを閉じるのを忘れおいたした。 他では、 streamむンスタンスが倉曎されるシナリオを凊理したせんでした
  • 䞀郚のりィゞェットが衚瀺されたずきに「メッセヌゞ」を既読ずしおマヌクする

これは、自分のアプリの1぀で発生した問題に䌌おいるため、興味深いケヌスです。そこで、コヌドをどのように実装したかを調べたしたが、このバグで説明されおいる問題はあたり芋られたせん。私が問題を理解するのに苊劎しおいる理由です。 これは問題のコヌドです

https://github.com/jocosocial/rainbowmonkey/blob/master/lib/src/views/forums.dart

問題が実際に発生しおいるこずを確認するために調査できる実際のアプリの䟋はありたすか

ずころで、䞀般的に、ストリヌムをたったく䜿甚しないこずを匷くお勧めしたす。䞀般的に、ストリヌムは事態を悪化させるず思いたす。

ずころで、䞀般的に、ストリヌムをたったく䜿甚しないこずを匷くお勧めしたす。䞀般的に、ストリヌムは事態を悪化させるず思いたす。

私は心から同意したす。しかし、コミュニティは珟圚反察の反応を瀺しおいたす。FlutterからChangeNotifier / Listenable / ValueNotifierを公匏パッケヌゞに抜出するず圹立぀かもしれたせん

問題が実際に発生しおいるこずを確認するために調査できる実際のアプリの䟋はありたすか

残念ながら違いたす。 私は他の人を助けおいる間に私が経隓したこずを共有するこずができるだけです。 手元にアプリがありたせん。

これは、自分のアプリの1぀で発生した問題に䌌おいるため、興味深いケヌスです。そこで、コヌドをどのように実装したかを調べたしたが、このバグで説明されおいる問題はあたり芋られたせん。私が問題を理解するのに苊劎しおいる理由です。 これは問題のコヌドです

実装では、ロゞックはラむフサむクルに関連付けられおおらず、_build_内に配眮されおいるため、問題を回避するこずができたす。
その特定の堎合には意味があるかもしれたせん。 その䟋が良かったかどうかはわかりたせん。

より良い䟋は、プルツヌリフレッシュです。

兞型的なプルトゥリフレッシュでは、次のこずが必芁になりたす。

  • 最初のビルドで、ロヌド/゚ラヌ状態を凊理したす
  • 曎新時

    • 画面が゚ラヌ状態だった堎合は、ロヌド画面をもう䞀床衚瀺したす

    • ロヌド䞭に曎新が実行された堎合は、保留䞭のHTTPリク゚ストをキャンセルしたす

    • 画面にデヌタが衚瀺された堎合

    • 新しい状態が読み蟌たれおいる間、デヌタを衚瀺し続けたす

    • 曎新が倱敗した堎合は、以前に取埗したデヌタを衚瀺し続け、゚ラヌのあるスナックバヌを衚瀺したす

    • 曎新が保留されおいる間にナヌザヌがポップしお画面に再び入る堎合は、ロヌド画面を衚瀺したす

    • 曎新が保留されおいる間、Re​​freshIndicatorが衚瀺されおいるこずを確認しおください

そしお、すべおのリ゜ヌスず耇数の画面にそのような機胜を実装したいず思いたす。 さらに、画面によっおは、䞀床に耇数のリ゜ヌスを曎新したい堎合がありたす。

ChangeNotifier + provider + StatefulWidgetは、このロゞックを因数分解するのに非垞に倚くの困難を䌎いたす。

私の最新の実隓䞍倉性に基づいおおり、 flutter_hooks䟝存しおいたすは、箱から出しおすぐにスペクトル党䜓をサポヌトしたす。

final productsProvider = FutureProvider<List<Product>>.autoDispose((ref) async {
  final cancelToken = CancelToken();
  ref.onDispose(cancelToken.cancel);

  return await repository.fetchProducts(cancelToken: cancelToken);
});

// ...

Widget build(context) {
  // Listens to the Future created by productsProvider and handles all the refresh logic
  AsyncValue<List<Product>> products = useRefreshProvider(
    productsProvider,
    // TODO consider making a custom hook to encaplusate the snackbar logic
    onErrorAfterRefresh: (err, stack) => Scaffold.of(context).showSnackBar(...),
  );

  return RefreshIndicator(
    onRefresh: () => context.refresh(productsProvider),
    child: products.when(
      loading: () {
        return const SingleChildScrollView(
          physics: AlwaysScrollableScrollPhysics(),
          child: CircularProgressIndicator(),
        );
      },
      error: (err, stack) {
        return SingleChildScrollView(
          physics: const AlwaysScrollableScrollPhysics(),
          child: Text('Oops, something unexpected happened\n$err'),
        );
      },
      data: (products) {
        return ListView.builder(
          itemCount: products.length,
          itemBuilder: (context, index) {
            return ProductItem(products[index]);
          },
        );
      },
    ),
  );
}

このロゞックは完党に自己完結型です。 これは、任意の画面内の任意のリ゜ヌスで再利甚できたす。

たた、1぀の画面で耇数のリ゜ヌスを䞀床に曎新したい堎合は、次のこずができたす。

AsyncValue<First> first = useRefreshProvider(
  firstProvider,
  onErrorAfterRefresh: ...
);
AsyncValue<Second> second = useRefreshProvider(
  secondProvider,
  onErrorAfterRefresh: ...
);

return RefreshIndicator(
  onRefresh: () {
     return Future.wait([context.refesh(firstProvider), context.refresh(secondProvider)]);
  }
  ...
)

そのロゞックをすべおりィゞェットの倖のアプリの状態にし、アプリの状態に珟圚のアプリの状態を反映させるこずをお勧めしたす。 プルしお曎新する堎合、りィゞェット内に状態は必芁ありたせん。曎新が保留䞭であるこずを呚囲の状態に通知し、その将来が完了するのを埅぀だけです。

゚ラヌずロヌドずデヌタのレンダリング方法を決定するのは、呚囲の状態の責任ではありたせん。

このロゞックをアンビ゚ント状態にしおも、UIからすべおのロゞックが削陀されるわけではありたせん。
UIは、゚ラヌを党画面衚瀺にするかスナックバヌに衚瀺するかを決定する必芁がありたす。
それでも、ペヌゞがリロヌドされたずきに゚ラヌを匷制的に曎新する必芁がありたす

そしお、これは再利甚性が䜎くなりたす。
レンダリングロゞックが呚囲の状態ではなくりィゞェットで完党に定矩されおいる堎合、それは_any_Futureで機胜したすFlutter内に盎接含めるこずもできたす。

私はあなたがあなたの最埌のコメントで䜕を䞻匵しおいるのか本圓に理解しおいたせん。 私のポむントは、前に匕甚したコヌドで瀺されおいるように、䞊蚘の曎新むンゞケヌタヌコヌドのように単玔なこずを行うためにフレヌムワヌクを倉曎する必芁がないずいうこずです。

曎新むンゞケヌタヌだけでなく、アニメヌションなどのこれらのタむプのむンタラクションが倚数ある堎合は、アプリの状態にするよりも、必芁に最も近い堎所にカプセル化する方がよいでしょう。アプリの状態だからです。アプリ内の耇数の堎所で必芁ない堎合は、アプリ内のすべおのむンタラクションの詳现を知る必芁はありたせん。

機胜の耇雑さずその再利甚性に぀いおは同意しおいないず思いたす。
そのような機胜が簡単であるこずを瀺す䟋はありたすか

䞊で曞いた1぀のアプリの゜ヌスにリンクしたした。 それは確かに完璧なコヌドではなく、次のリリヌスのためにその䞀郚を曞き盎す予定ですが、この号で説明した問題は発生したせんでした。

しかし、あなたはFlutterの技術リヌダヌの1人です。
問題に盎面した堎合でも、すぐに解決策を考え出すのに十分なスキルがありたす。

しかし䞀方で、かなりの数の人々が次のコヌドの䜕が問題なのかを理解しおいたせん。

FutureBuilder<User>(
  future: fetchUser(),
  builder: ...,
)

この事実は、StackOverflowでQ / AIがどれほど人気が​​あるかによっお蚌明されおいたす。

問題は、再利甚可胜で堅牢な方法で状態ロゞックを抜象化するこずが䞍可胜であるずいうこずではありたせんそうでなければ、この問題を䜜成しおも意味がありたせん。
問題は、そうするのに時間ず経隓の䞡方が必芁なこずです。

公匏の゜リュヌションを提䟛するこずで、アプリケヌションが保守䞍胜になる可胜性が䜎くなり、党䜓的な生産性ず開発者の゚クスペリ゚ンスが向䞊したす。
誰もがあなたの物件の提案を思い付くこずができるわけではありたせん。 そのようなものがFlutter内に構築された堎合、それは文曞化され、可芖性を獲埗し、最終的には最初から考えたこずのない人々を支揎したす。

問題は、アプリが䜕であるか、状態がどのように芋えるかなどに実際に䟝存するこずです。 ここでの質問が「アプリの状態をどのように管理するか」である堎合、答えはフックのようなものではありたせん。それを行うためのさたざたな方法に぀いお説明し、さたざたな状況に応じおさたざたな手法を掚奚する倚くのドキュメントです...基本的に、この䞀連のドキュメント https 

䞀時的な状態ずアプリの状態がありたすが、別のナヌスケヌスもあるようです。単䞀のタむプのりィゞェットのみに関係するが、それでもそのタむプのりィゞェット間で共有したい状態です。

たずえば、 ScrollControllerはある皮のアニメヌションを呌び出す堎合がありたすが、それをグロヌバルアプリの状態にするこずは必ずしも適切ではありたせん。これは、アプリ党䜓で䜿甚する必芁のあるデヌタではないためです。 ただし、耇数のScrollControllerが同じロゞックを持っおいる可胜性があり、それぞれの間でそのラむフサむクルロゞックを共有する必芁がありたす。 状態はただScrollControllerだけなので、グロヌバルアプリの状態ではありたせんが、ロゞックをコピヌしお貌り付けるず゚ラヌが発生しやすくなりたす。

さらに、このロゞックをパッケヌゞ化しお、将来のプロゞェクトだけでなく、他のプロゞェクトでもより構成しやすくするこずができたす。 サむトuseHooksを芋るず、特定の䞀般的なアクションを区分化するロゞックの倚くの郚分がわかりたす。 useAuthを䜿甚する堎合は、䞀床曞き蟌むだけで、 initStateたたはdispose呌び出しを逃したかどうか、たたは非同期関数にthenがあるかどうかを心配する必芁はありたせん。 catch 。 関数は䞀床だけ曞かれるので、゚ラヌの䜙地は基本的になくなりたす。 したがっお、この皮の゜リュヌションは、同じアプリの耇数の郚分や耇数のアプリ間でより構成しやすいだけでなく、゚ンドプログラマヌにずっおも安党です。

私はフックを䜿甚しおいる人々に異議はありたせん。 私の知る限り、それを劚げるものは䜕もありたせん。 䜕かがそれを劚げおいる堎合は、それに぀いおバグを報告しおください。

このバグはフックに関するものではなく、「状態ロゞックの再利甚は冗長/困難すぎる」に関するものであり、これがFlutterぞの倉曎を必芁ずする理由を理解するのにただ苊劎しおいたす。 アプリケヌションを䜕らかの方法で構造化するこずで冗長性を回避する方法を瀺す倚くの䟋フックを含むがあり、それに関するドキュメントはすでにたくさんありたす。

なるほど、Flutterを倉曎せずにビルドされたフックパッケヌゞのようなものが存圚する堎合、フックのファヌストパヌティ゜リュヌションが必芁なのはなぜですか @rrousselGitはこれによりよく答えるこずができるず

衚面䞊はflutter_hooksパッケヌゞがすでに存圚するため、それに加えお、フックをサポヌトするためにFlutterに基本的な倉曎を加える必芁がある理由も混乱しおいたす。

Flutterに倉曎が必芁な理由を理解するのにただ苊劎しおいたす。

コミュニティがパッケヌゞを䜜成したためにこの問題が解決したず蚀うこずは、私がFreezedを䜜成したため、Dartはデヌタクラスず共甚䜓型を必芁ずしないず蚀っおいるようなもの
Freezedは、これらの問題の䞡方の解決策ずしおコミュニティに非垞に奜たれおいるかもしれたせんが、それでも私たちはもっずうたくやるこずができたす。

Flutterチヌムは、コミュニティがこれたで以䞊に掻​​甚しおいたす。 スタック党䜓を倉曎する䞡方の機胜がありたす。 個々の郚分の専門家である人々。 そしお必芁な仕事を埌揎するための絊料。

この問題にはそれが必芁です。
泚意Reactチヌムの目暙の1぀は、JSXのように、フックを蚀語の䞀郚にするこずです。

蚀語のサポヌトがなくおも、アナラむザヌでの䜜業が必芁です。 ダヌトパッド; flutter / devtools; たた、Flutterが行うさたざたなこずすべおを単玔化するための倚くのフック暗黙のアニメヌション、フォヌムなど。

Flutterの䞀般的な哲孊は小さなコアを持っおいるずはいえ、それは良い議論だず私は同意したす。 そのため、Googleからのものであっおも、パッケヌゞずしお新しい機胜を远加するこずが増えおいたす。文字やアニメヌションを参照しおください。 これにより、時間の経過ずずもに孊習および倉曎するための柔軟性が高たりたす。 パッケヌゞが䞍十分であるずいう説埗力のある技術的な理由がない限り、このスペヌスに぀いおも同じこずを行いたすそしお、拡匵メ゜ッドを䜿甚するず、これたで以䞊に可胜性が䜎くなりたす。

Flutterのコアに物事を入れるのは難しいです。 盎接の経隓からよく知っおいるように、1぀の課題は、リアクティブUIアヌキテクチャで䜕がうたく機胜するかに぀いお私たち党員が孊ぶに぀れお、状態が進化しおいる領域であるずいうこずです。 2幎前、勝者を遞ぶこずを䜙儀なくされた堎合は、BLoCを遞択した可胜性がありたすが、もちろん、プロバむダヌパッケヌゞが匕き継がれ、珟圚はデフォルトの掚奚事項です。

私は、flutter_hooksたたは牜匕力のある同様のフックパッケヌゞをサポヌトするGoogle採甚の貢献者を快適に想像するこずができたしたもちろん、私たちの泚意を奪い合う他の仕事は

興味深い議論、@ timsneath。 Rustコミュニティも同様のこずを行いたす。蚀語たたはフレヌムワヌクのコアラむブラリたたは暙準ラむブラリに導入されるず、それを取り出すのが非垞に難しいためです。 Rustの堎合、䞋䜍互換性を氞久に維持したいので䞍可胜です。 したがっお、圌らはパッケヌゞが到着するたで埅ち、少数の勝者だけが珟れるたで互いに競争し、それからそれを蚀語に折り畳みたす。

これは、Flutterの堎合ず同様のケヌスである可胜性がありたす。 Reactがクラスからフックに移動しなければならなかったが、それでもクラスを維持しなければならず、人々が移行しなければならなかったように、埌でフックよりも良いものがあるかもしれたせん。 その堎合、コアに远加する前に、競合する状態管理゜リュヌションを甚意する方がよい堎合がありたす。 そしお、おそらく私たちコミュニティは、フックの䞊で革新するか、さらに良い解決策を芋぀けようずする必芁がありたす。

私はその懞念を理解しおいたすが、これは状態管理゜リュヌションに関するものではありたせん。

このような機胜は、AttachedwidgetずStatefulWidgetに近いものです。 これは䜎レベルのプリミティブであり、蚀語機胜ず同じくらい䜎くなる可胜性がありたす。

フックはフレヌムワヌクから独立しおいるかもしれたせんが、それは運によっおのみです。
前に述べたように、この問題ぞの別のパスは次のようになりたす。

context.onDispose(() {

});

そしお同様のむベントリスナヌ。
しかし、それをフレヌムワヌクから実装するこずは䞍可胜です。

チヌムが䜕を思い぀くのかわかりたせん。
しかし、そのような゜リュヌションがElementのすぐ隣になければならない可胜性を排陀するこずはできたせん

拡匵機胜はそれを助けたすか

ただし、別の問題でそれに぀いお話す必芁があるかもしれたせん。ここではトピックから倖れおいたす。人々が目にしおいる問題ごずに1぀の問題があれば、適切な堎所で解決策に぀いお話し合うこずができればず思いたす。そうではありたせん。 context.onDisposeが冗長性にどのように圹立぀かを明確にしたす。

これに関連しお私たちが思い぀くこずができるいく぀かの本圓に良い蚀語の提案があるず匷く思いたす。

それらが特定の状態管理むディオムをどのように可胜にするかよりも、それらに぀いおより具䜓的に話すこずが圹立぀ず思いたす。 次に、それらが䜕を可胜にし、どのようなトレヌドオフを䌎う可胜性があるかをより真剣に怜蚎するこずができたす。

特に、VMランタむムずJSランタむムの䞡方でどのように機胜するかを怜蚎するこずができたす。

context.onDisposeが冗長性にどのように圹立぀かは明確ではありたせん。

前に述べたように、この問題は冗長性よりもコヌドの再利甚性に関するものです。 しかし、より倚くのコヌドを再利甚できる堎合、これは暗黙的に冗長性を枛らすはずです。

context.onDisposeがこの問題に関連する方法は、珟圚の構文では次のずおりです。

AnimationController controller;

<strong i="11">@override</strong>
void initState() {
  controller = AnimationController(...);
}

<strong i="12">@override</strong>
void dispose() {
  controller.dispose();
}

問題は

  • これはクラス定矩ず緊密に結合されおいるため、再利甚できたせん
  • りィゞェットが倧きくなるず、途䞭に数癟行のコヌドがあるため、初期化ず砎棄の関係が読みにくくなりたす。

context.onDispose 、次のこずができたす。

<strong i="21">@override</strong>
void initState() {
  controller = AnimationController(...);
  context.onDispose(controller.dispose);
}

興味深い郚分は次のずおりです。

  • これはもはやクラス定矩ず緊密に結合されおいないため、関数に抜出できたす。
    理論的には、半耇雑なロゞックを持぀こずができたす。
    `` `ダヌツ
    AnimationController someReusableLogicBuildContext context{
    最終コントロヌラヌ= AnimationController...;
    controller.onDisposecontroller.dispose;
    controller.forward;
    void listener{}
    controller.addListenerlistener;
    context.onDispose=> controller.removeListenerlistener;
    }
    ..。

@オヌバヌラむド
void initState{
コントロヌラヌ= someReusableLogiccontext;
}
`` `

  • すべおのロゞックがバンドルされおいたす。 りィゞェットの長さが300に増えおも、 controllerのロゞックは簡単に読み取るこずができたす。

このアプロヌチの問題は次のずおりです。

  • context.myLifecycle(() {...})はホットリロヌドできたせん
  • 関数をりィゞェット定矩に緊密に結合せずに、 someReusableLogicにStatefulWidgetからプロパティを読み取らせる方法は䞍明です。
    たずえば、 AnimationControllerのDurationりィゞェットのパラメヌタずしお枡すこずができたす。 したがっお、期間が倉化するシナリオを凊理する必芁がありたす。
  • ValueNotifierに頌ったり、リスナヌを凊理したりせずに、時間の経過ずずもに倉化する可胜性のあるオブゞェクトを返す関数を実装する方法は䞍明です。

    • これは、蚈算された状態にずっお特に重芁です。


蚀語の提案に぀いお考えたす。 私にはいく぀かのアむデアがありたすが、今話す䟡倀のあるものは䜕もありたせん。

前に述べたように、この問題は冗長性よりもコヌドの再利甚性に関するものです

Ok。 それに぀いお具䜓的に説明しおいる新しいバグを提出しおいただけたせんか このバグは、文字通り「状態ロゞックの再利甚は冗長/困難すぎる」ず呌ばれたす。 冗長性が問題ではない堎合、_this_は問題ではありたせん。

context.onDispose 、次のこずができたす。

<strong i="11">@override</strong>
void initState() {
  controller = AnimationController(...);
  context.onDispose(controller.dispose);
}

contextがこれに関連する理由がわかりたせんそしおonDisposeは呜名芏則に違反しおいたす。 ただし、砎棄䞭に実行するものを登録する方法が必芁な堎合は、今日これを簡単に行うこずができたす。

mixin StateHelper<T extends StatefulWidget> on State<T> {
  List<VoidCallback> _disposeQueue;

  void queueDispose(VoidCallback callback) {
    _disposeQueue ??= <VoidCallback>[];
    _disposeQueue.add(callback);
  }

  <strong i="17">@override</strong>
  void dispose() {
    if (_disposeQueue != null) {
      for (VoidCallback callback in _disposeQueue)
        callback();
    }
    super.dispose();
  }
}

このように呌んでください

class _MyHomePageState extends State<MyHomePage> with StateHelper<MyHomePage> {
  TextEditingController controller;

  <strong i="21">@override</strong>
  void initState() {
    super.initState();
    controller = TextEditingController(text: 'button');
    queueDispose(controller.dispose);
  }

  ...
AnimationController someReusableLogic(BuildContext context) {
  final controller = AnimationController(...);
  controller.onDispose(controller.dispose);
  controller.forward();
  void listener() {}
  controller.addListener(listener);
  context.onDispose(() => controller.removeListener(listener));
}
...

<strong i="25">@override</strong>
void initState() {
  controller = someReusableLogic(context);
}

あなたもそれを行うこずができたす

AnimationController someReusableLogic<T extends StatefulWidget>(StateHelper<T> state) {
  final controller = AnimationController(...);
  state.queueDispose(controller.dispose);
  controller.forward();
  void listener() {}
  controller.addListener(listener);
  state.queueDispose(() => controller.removeListener(listener));
  return controller;
}
...

<strong i="6">@override</strong>
void initState() {
  controller = someReusableLogic(this);
}

このアプロヌチの問題は次のずおりです。

  • context.myLifecycle(() {...})はホットリロヌドできたせん

このコンテキストでは、initStateで呌び出されるものだけのためであるため、問題ではないようです。 私は䜕かが足りないのですか

  • 関数をりィゞェット定矩に緊密に結合せずに、 someReusableLogicにStatefulWidgetからプロパティを読み取らせる方法は䞍明です。
    たずえば、 AnimationControllerのDurationりィゞェットのパラメヌタずしお枡すこずができたす。 したがっお、期間が倉化するシナリオを凊理する必芁がありたす。

disposeキュヌず同じように、didChangeWidgetキュヌを远加するのは非垞に簡単です。

mixin StateHelper<T extends StatefulWidget> on State<T> {
  List<VoidCallback> _disposeQueue;
  List<VoidCallback> _didUpdateWidgetQueue;

  void queueDispose(VoidCallback callback) {
    _disposeQueue ??= <VoidCallback>[];
    _disposeQueue.add(callback);
  }

  void queueDidUpdateWidget(VoidCallback callback) {
    _didUpdateWidgetQueue ??= <VoidCallback>[];
    _didUpdateWidgetQueue.add(callback);
  }

  <strong i="24">@override</strong>
  void didUpdateWidget(T oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (_didUpdateWidgetQueue != null) {
      for (VoidCallback callback in _didUpdateWidgetQueue)
        callback();
    }
  }

  <strong i="25">@override</strong>
  void dispose() {
    if (_disposeQueue != null) {
      for (VoidCallback callback in _disposeQueue)
        callback();
    }
    super.dispose();
  }
}

AnimationController conditionalAnimator(StateHelper state, ValueGetter<bool> isAnimating, VoidCallback listener) {
  final controller = AnimationController(vsync: state as TickerProvider, duration: const Duration(seconds: 1));
  state.queueDispose(controller.dispose);
  controller.addListener(listener);
  state.queueDispose(() => controller.removeListener(listener));
  if (isAnimating())
    controller.repeat();
  state.queueDidUpdateWidget(() {
    if (isAnimating()) {
      controller.repeat();
    } else {
      controller.stop();
    }
  });
  return controller;
}

このように䜿甚されたす

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  <strong i="6">@override</strong>
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(animating: false),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.animating}) : super(key: key);

  final bool animating;

  <strong i="7">@override</strong>
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with StateHelper<MyHomePage>, SingleTickerProviderStateMixin {
  AnimationController controller;

  <strong i="8">@override</strong>
  void initState() {
    super.initState();
    controller = conditionalAnimator(this, () => widget.animating, () { print(controller.value); });
  }

  <strong i="9">@override</strong>
  Widget build(BuildContext context) {
    return Center(
      child: FadeTransition(
        opacity: controller,
        child: Text('Hello', style: TextStyle(fontSize: 100.0, color: Colors.white)),
      ),
    );
  }
}
  • ValueNotifierに頌ったり、リスナヌを凊理したりせずに、時間の経過ずずもに倉化する可胜性のあるオブゞェクトを返す関数を実装する方法は䞍明です。

    • これは、蚈算された状態にずっお特に重芁です。

これがここで䜕を意味するのかわからない、ValueNotifier、たずえばValueListenableBuilderの䜕が問題になっおいたすか

前に述べたように、この問題は冗長性よりもコヌドの再利甚性に関するものです

Ok。 それに぀いお具䜓的に説明しおいる新しいバグを提出しおいただけたせんか このバグは、文字通り「状態ロゞックの再利甚は冗長/困難すぎる」ず呌ばれたす。 冗長性が問題ではない堎合、これは問題ではありたせん。

私はこの議論にかなり䞍快になり始めおいたす。 私はすでにこの点に前に答えたした
この問題のトピックは再利甚性であり、冗長性は再利甚性の問題の結果ずしお議論されたす。 䞻芁なトピックずしおではありたせん。

䞊郚のコメントには、冗長性に぀いお蚀及しおいる箇条曞きが1぀だけありたす。これは、䞻に2぀のレベルのむンデントを察象ずするStreamBuilderの堎合です。

なぜコンテキストがこれに関連するのかわかりたせん[...]。 ただし、砎棄䞭に実行するものを登録する方法が必芁な堎合は、今日これを簡単に行うこずができたす。

context.onDispose立ち䞊げたずき、私はそれが良い解決策ではないずはっきり蚀った。
それが議論ずどのように関係しおいるかを尋ねられたので、私はそれを説明したした。

なぜに関しおはcontextの代わりにStateHelperこれはStatelessWidgetでの䜜業のように、より柔軟性があるので、それはありたす

context.myLifecycle{...}はホットリロヌド可胜ではありたせん

このコンテキストでは、initStateで呌び出されるものだけのためであるため、問題ではないようです。 私は䜕かが足りないのですか

倉曎される可胜性がありたす

initState() {
  context.myLifecycle(() => print('hello'));
}

の䞭ぞ

initState() {
  context.myLifecycle(() => print('world'));
}

これは、 myLifecycleコヌルバックぞの倉曎を適甚したせん。

しかし、䜿甚した堎合

myLifecycle() {
  super.myLifecycle();
  print('hello');
}

その埌、ホットリロヌドが機胜したす。

これがここで䜕を意味するのかわからない、ValueNotifier、たずえばValueListenableBuilderの䜕が問題になっおいたすか

この構文は、Builderを䜿甚する必芁がないように蚭蚈されおいるため、元の問題に戻りたした。

さらに、関数を本圓に構成可胜にしたい堎合は、 ValueGetter + queueDidUpdateWidget提案ではなく、関数はパラメヌタヌずしおValueNotifierを取る必芁がありたす。

AnimationController conditionalAnimator(StateHelper state, ValueListenable<bool> isAnimating, VoidCallback listener) {
...
}

この関数を䜿甚しおいるりィゞェットによっおは、 didUpdateWidget以倖の堎所からisAnimatingを取埗したい堎合があるためです。
ある堎所では、didUpdateWidgetかもしれたせん。 別の䟋では、didChangeDependenciesである可胜性がありたす。 さらに別の堎所では、 stream.listenのコヌルバック内にある可胜性がありたす。

しかし、これらのシナリオを簡単にValueNotifierに倉換し、関数にそのような通知機胜をリッスンさせる方法が必芁です。
ですから、私たちは私たちの生掻を著しく困難にしおいたす。
私が思うこのパタヌンよりも、 ConditionalAnimatorBuilderを䜿甚する方が珟実的で簡単です。

なぜに関しおはcontextの代わりにStateHelperこれはStatelessWidgetでの䜜業のように、より柔軟性があるので、それはありたす

StatelessWidgetは、ステヌトレスりィゞェット甚です。 重芁なのは、状態を䜜成したり、物を砎棄したり、didUpdateWidgetに反応したりしないずいうこずです。

はい、ホットリロヌドのこずです。 そのため、initStateにクロヌゞャを配眮するのではなくメ゜ッドを䜿甚したす。

申し蚳ありたせんが、これを蚀い続けおおり、むラむラしおいるに違いないこずは理解しおいたすが、ここで解決しようずしおいる問題が䜕であるかはただわかりたせん。 元のバグの芁玄ず元の説明の倧郚分によるず、それは冗長だず思いたしたが、そうではないこずを理解しおいたす。 それで、問題は䜕ですか ここには盞互に排他的な欲求がたくさんあり、このバグの倚くのコメントに広がっおいるようです。

  • 䜕かを凊分する方法を宣蚀するこずは、それを割り圓おるのず同じ堎所で行われるべきです...
  • ...そしおそれを割り圓おる堎所はそれを割り圓おおいるので䞀床だけ実行する必芁がありたす...
  • ...そしお、ホットリロヌドで動䜜する必芁がありたす定矩䞊、1回だけ実行されるコヌドは再実行されたせん...
  • ...そしお、ステヌトレスりィゞェット定矩䞊、状態を持たないで機胜する状態を䜜成できる必芁がありたす...
  • ...そしお、didUpdateWidgetやdidChangeDependenciesなどぞのフックを有効にする必芁がありたす...

私たちがここで関わっおいるこの反埩的なダンスは、物事を成し遂げるための生産的な方法ではありたせん。 前にも蚀ったように、ここで䜕かを埗るための最良の方法は、盎面しおいる問題を理解できる方法で説明し、すべおのニヌズを1か所で説明し、ナヌスケヌスで説明するこずです。 ゜リュヌションをリストしないこずをお勧めしたす。特に、ニヌズを満たさないこずがわかっおいる゜リュヌションはリストしないこずをお勧めしたす。 これらの゜リュヌションを䞍適切にする必芁性が説明に蚘茉されおいるこずを確認しおください。

正盎なずころ、基本的にはたったく異なるフレヌムワヌク蚭蚈を求めおいるように思えたす。 それはたったく問題ありたせんが、Flutterではありたせん。 別のフレヌムワヌクを実行する堎合、それは別のフレヌムワヌクになりたすが、_this_フレヌムワヌクで実行する䜜業はただたくさんありたす。 実際、あなたが説明するこずの倚くは、JetpackComposeの蚭蚈方法ず非垞に䌌おいたす。 コンパむラの魔法が必芁なため、私はそのデザむンの倧ファンではないので、䜕が起こっおいるのかをデバッグするのは本圓に難しいですが、倚分それはあなたの路地にありたすか

ここには盞互に排他的な欲求がたくさんあり、このバグの倚くのコメントに広がっおいるようです。

それらは盞互に排他的ではありたせん。 フックはこれらのすべおを実行したす。 ゜リュヌションに焊点を圓おたくないので、詳现には立ち入りたせんが、すべおのチェックボックスをオンにしたす。

前にも蚀ったように、ここで䜕かを埗るための最良の方法は、盎面しおいる問題を理解できる方法で説明し、すべおのニヌズを1か所で説明し、ナヌスケヌスで説明するこずです。

私はただそのトップコメントがそれをどのように倱敗するのか理解できたせん。
他の人に䜕がはっきりしおいないのか、私にはわかりたせん。

実際、あなたが説明するこずの倚くは、JetpackComposeの蚭蚈方法ず非垞に䌌おいたす。 コンパむラの魔法が必芁なため、私はそのデザむンの倧ファンではないので、䜕が起こっおいるのかをデバッグするのは本圓に難しいですが、倚分それはあなたの路地にありたすか

私はそれをよく知らないが、簡単な怜玢で、私は_yes_ず蚀うだろう。

それらは盞互に排他的ではありたせん。

䞊蚘のすべおの箇条曞きは、ここで解決しようずしおいる問題の䞀郚ですか

しかし、圌らはすべおのボックスをチェックしたす

ボックスをリストできたすか

私はただそのトップコメントがそれをどのように倱敗するのか理解できたせん。

たずえば、OPは、問題はStatefulWidgetsに関するものであるず明瀺的に述べおいたすが、この問題に関する最近のコメントの1぀は、StatelessWidgetsで機胜しなかったため、特定の提案は適切ではないず述べたした。

OPであなたは蚀う

Stateロゞックを再利甚するこずは困難です。 最終的に耇雑で深くネストされたbuildメ゜ッドになるか、耇数のりィゞェット間でロゞックをコピヌしお貌り付ける必芁がありたす。

したがっお、これから、芁件には次のものが含たれおいるず思いたす。

  • ゜リュヌションを深くネストしおはなりたせん。
  • ゜リュヌションは、状態を远加しようずする堎所に倚くの同様のコヌドを必芁ずしおはなりたせん。

最初のポむントネスティングに぀いおは問題ないようです。 深くネストされたものを実行する必芁があるこずを瀺唆しようずはしおいたせん。 ずはいえ、䜕が深くネストされおいるかに぀いおは意芋が分かれる可胜性がありたす。これはここでは定矩されおいたせん。埌で他のコメントは、ビルダヌが深くネストされたコヌドを匕き起こすこずを瀺唆しおいたすが、私の経隓では、ビルダヌはかなり優れおいたす。

2番目のポむントは、冗長性がないずいう芁件であるように思われたす。 しかし、あなたはこれが冗長性に぀いおではないこずを䜕床か説明したした。

OPが行う次のステヌトメントは、問題を説明しおいたす。

Stateロゞックを耇数のStatefulWidgetたたがっお再利甚するこずは、そのロゞックが耇数のラむフサむクルに䟝存するようになるずすぐに非垞に困難になりたす。

正盎なずころ、これが䜕を意味するのか本圓にわかりたせん。 私にずっお「難しい」ずは、通垞、理解しにくい耇雑なロゞックがたくさん含たれおいるこずを意味したすが、ラむフサむクルむベントの割り圓お、砎棄、および察応は非垞に簡単です。 問題を䞎える次のステヌトメントここでは、「耇雑ではない」ず明瀺的に説明されおいるため、おそらく問題の説明ではない䟋をスキップしおいたすは次のずおりです。

問題は、そのアプロヌチを拡匵したいずきに始たりたす。

これは、「非垞に難しい」ずは「非垞に冗長」を意味し、「耇雑ではない」䟋ず「非垞に難しい」の䟋の唯䞀の違いは、同様のコヌドが倚数出珟するこずから生じるこずを瀺唆したした。 「䟋をスケヌリングした結果は、文字通り、同じコヌドが䜕床も発生するずいうこずです぀たり、冗長性、定型コヌド。

これは、問題を説明する次のステヌトメントによっおさらにサポヌトされたす。

このロゞックをどこにでもコピヌしお貌り付けるず「機胜」したすが、コヌドに匱点が生じたす。

  • 手順の1぀を曞き盎すのを忘れがちです dispose呌び出しを忘れるなど

コヌドをコピヌしお貌り付けるずきに冗長性があるため、間違いを犯しやすいため、おそらく非垞に難しいのでしょうか。 しかし、繰り返しになりたすが、私が「冗長性」ず衚珟するこの問題に察凊しようずしたずき、問題は冗長性ではないずおっしゃいたした。

  • コヌドに倚くのノむズを远加したす

繰り返しになりたすが、これは私に冗長性/ボむラヌプレヌトを蚀っおいるように聞こえたすが、それはそうではないず説明したした。

OPの残りの郚分は、気に入らない解決策を説明しおいるだけなので、おそらく問題を説明しおいたせん。

これは、OPが問題を説明できない方法を説明しおいたすか OP内で実際に問題を説明しおいるものはすべお冗長性を説明しおいるように芋えたすが、それが問題であるず提案するたびに、そうではなく、別の問題があるず蚀いたす。

誀解は蚀葉の意味に垰着するず思いたす。
䟋えば

コヌドに倚くのノむズを远加したす

繰り返しになりたすが、これは私に冗長性/ボむラヌプレヌトを蚀っおいるように聞こえたすが、それはそうではないず説明したした。

この点は、 controller.dispose()の数ではなく、これらのコヌド行が読者にもたらす䟡倀です。
その線は垞にそこにあるべきであり、垞に同じです。 そのため、リヌダヌに察するその倀はほずんどnullです。

重芁なのは、この線の存圚ではなく、その䞍圚です。

問題は、そのようなcontroller.dispose()が倚ければ倚いほど、disposeメ゜ッドで実際の問題を芋逃す可胜性が高くなるこずです。
コントロヌラヌが1぀、廃棄が0の堎合、簡単にキャッチできたす。
100個のコントロヌラヌず99個の廃棄がある堎合、䞍足しおいるコントロヌラヌを芋぀けるのは困難です。

次に、次のようになりたす。

コヌドをコピヌしお貌り付けるずきに冗長性があるため、間違いを犯しやすいため、おそらく非垞に難しいのでしょうか。 しかし、繰り返しになりたすが、私が「冗長性」ず衚珟するこの問題に察凊しようずしたずき、問題は冗長性ではないずおっしゃいたした。

前のポむントで述べたように、コヌドのすべおの行が等しいわけではありたせん。

比范するず

+ T state;

<strong i="24">@override</strong>
void initState() {
  super.initState();
+  state = widget.valueNotifier.value;
+  widget.valueNotifier.addListener(_listener);
}

+ void _listener() => seState(() => state = widget.valueNotifier.value);

void dispose() {
+ widget.valueNotifier.removeListener(_listener);
  super.dispose();
}

察

+ ValueListenableBuilder<T>(
+   valueListenable: widget.valueNotifier,  
+   builder: (context, value, child) {

+    },
+ );

その堎合、これらのスニペットは䞡方ずも同じ行数を持ち、同じこずを行いたす。
ただし、 ValueListenableBuilderが望たしいです。

その理由は、重芁なのは行数ではなく、これらの行が䜕であるかずいうこずです。

最初のスニペットには次のものがありたす。

  • 1぀のプロパティ宣蚀
  • 1぀のメ゜ッド宣蚀
  • 1぀の割り圓お
  • 2぀のメ゜ッド呌び出し
  • これらはすべお、2぀の異なるラむフサむクルにたたがっおいたす。 3ビルドを含める堎合

2番目のスニペットには次のものがありたす。

  • 1クラスのむンスタンス化
  • 1぀の無名関数
  • ラむフサむクルはありたせん。 ビルドを含める堎合は1

これにより、ValueListenableBuilderが_simpler_になりたす。

これらの行が蚀っおいないこずもありたす
ValueListenableBuilderは、時間の経過に䌎うvalueListenable倉化を凊理したす。
widget.valueNotifierが時間の経過ずずもに倉化しないシナリオでも、問題はありたせん。
ある日、その声明は倉わるかもしれたせん。 この堎合、ValueListenableBuilderは新しい動䜜を適切に凊理したすが、最初のスニペットではバグが発生しおいたす。

したがっお、ValueListenableBuilderは単玔であるだけでなく、たったく同じ行数で、コヌドの倉曎に察する耐性も高くなりたす。


これで、ValueListenableBuilderが望たしいずいうこずには同意できるず思いたす。
問題は、「すべおの再利甚可胜な状態ロゞックにValueListenableBuilderず同等のものがないのはなぜですか」です。

たずえば、次の代わりに

final controller = TextEditingController(text: 'hello world');
...
controller.dispose();

私たちは持っおいるでしょう

TextEditingControllerBuilder(
  initialText: 'hello world',
  builder: (context, controller) {

  },
);

initialTextぞの倉曎をホットリロヌドできるずいう远加の利点がありたす。

この䟋は少し些现なこずかもしれたせんが、この原則を少し高床な再利甚可胜な状態ロゞック ModeratorBuilder に䜿甚できたす。

これは小さなスニペットでは「問題ありたせん」。 しかし、アプロヌチを拡匵したいので、いく぀かの問題が発生したす。

  • ビルダヌは「ノむズが倚すぎる」問題に戻りたす。

たずえば、次のようにモデルを管理しおいる人がいたす。

class User {
  final ValueNotifier<String> name;
  final ValueNotifier<int> age;
  final ValueNotifier<Gender> gender;
}

しかし、りィゞェットは、 name 、 age 、およびgender䞡方を䞀床にリッスンしたい堎合がありたす。
぀たり、次のこずを行う必芁がありたす。

return ValueListenableBuilder<String>(
  valueListenable: user.name,
  builder: (context, userName, _) {
    return ValueListenableBuilder<int>(
      valueListenable: user.age,
      builder: (context, userAge, _) {
        return ValueListenableBuilder<Gender>(
          valueListenable: user.gender,
          builder: (context, userGender, _) {
            return Text('$userGender. $userName ($userAge)');
          },
        );
      },
    );
  },
);

これは明らかに理想的ではありたせん。 initState / dispose内の汚染を陀去しお、 buildメ゜ッドを汚染したした。

䟋のためにListenable.mergeを無芖したしょう。ここでは重芁ではありたせん。構成に぀いおです

Builderを広範囲に䜿甚した堎合、この正確なシナリオで自分自身を簡単に確認できたす。 Listenable.merge盞圓するもの

  • カスタムビルダヌを曞くのは面倒です

    Builderを䜜成する簡単な解決策はありたせん。 ここではリファクタリングツヌルは圹に立ちたせん。単に「ビルダヌずしお抜出」するこずはできたせん。
    さらに、それは必ずしも盎感的ではありたせん。 カスタムビルダヌを䜜成するこずは、人々が最初に考えるこずではありたせん。特に、倚くの人が定型文に反察するでしょう私はそうではありたせんが。

    人々はカスタムの状態管理゜リュヌションを䜜成する可胜性が高く、最終的には䞍良コヌドになる可胜性がありたす。

  • ビルダヌのツリヌを操䜜するのは面倒です

    前の䟋でValueListenableBuilderを削陀するか、新しい䟋を远加したいずしたすが、これは簡単ではありたせん。
    コヌドがコンパむルされない理由を理解するために、ず{}のカりントに数分費やすこずができたす。


今述べたBuilderの問題を解決するためのフックがありたす。

前の䟋をフックにリファクタリングするず、次のようになりたす。

final userName = useValueListenable(user.name);
final useAge = useValueListenable(user.age);
final useGender = useValueListenable(user.gender);

return Text('$userGender. $userName ($userAge)');

以前の動䜜ず同じですが、コヌドに線圢むンデントが远加されたした。
぀たり

  • コヌドが倧幅に読みやすくなりたした
  • 線集が簡単です。 恐れる必芁はありたせん{}; 新しい行を远加したす。

それはメむンのproviderが奜きなものの1぀です。 MultiProvider導入するこずで、倚くのネストを削陀したした。

同様に、 initState / disposeアプロヌチずは察照的に、ホットリロヌドの恩恵を受けたす。
新しいuseValueListenableを远加した堎合、倉曎はすぐに適甚されたす。

そしおもちろん、再利甚可胜なプリミティブを抜出する機胜はただありたす。

String useUserLabel(User user) {
  final userName = useValueListenable(user.name);
  final useAge = useValueListenable(user.age);
  final useGender = useValueListenable(user.gender);

  return '$userGender. $userName ($userAge)';
}

Widget build(context) {
  final label = useUserLabel(user);
  return Text(label);
}

このような倉曎はextract as functionで自動化でき、ほずんどのシナリオで機胜したす。


それはあなたの質問に答えたすか

もちろん。 しかし、そのようなものの問題は、実際に正しいこずを行うのに十分な情報がないこずです。 䟋えば

Widget build(context) {
  if (random.nextBool())
    final title = useLabel(title);
  final label = useLabel(name);
  return Text(label);
}

...本圓に玛らわしい方法でバグが発生するこずになりたす。

コンパむラの魔法でそれを回避するこずができたすがComposeはそれを行う方法です、Flutterの堎合、基本的な蚭蚈䞊の決定の䞀郚に違反したす。 キヌを䜿甚しお回避するこずはできたすが、パフォヌマンスが倧幅に䜎䞋し倉数ルックアップにはマップルックアップやハッシュなどが含たれるため、Flutterの基本的な蚭蚈目暙の䞀郚に違反したす。

以前に提案したプロパティ゜リュヌション、たたはそれから掟生したものは、すべおのコヌドを1か所にたずめるずいう前述の目暙を達成しながら、コンパむラの魔法を回避しおいるようです。 なぜそれがうたくいかないのか、私にはよくわかりたせん。 明らかに、didChangeDependenciesなどにもフックしお完党な゜リュヌションにするように拡匵されたす。パフォヌマンス芁件に違反するため、これを基本フレヌムワヌクに配眮したせん。

あなたが蚀うように、発生する可胜性のあるバグが原因で、フックを条件付きで呌び出すべきではありたせん。 詳现に぀いおは、ReactJSのRules ofHooksドキュメントを参照しおください。 基本的な芁点は、それらの実装では呌び出し順序によっお远跡されるため、条件付きで䜿甚するずその呌び出し順序が壊れ、正しく远跡できなくなるずいうこずです。 フックを適切に䜿甚するには、条件付きロゞックなしでbuildのトップレベルでフックを呌び出したす。 JSバヌゞョンでは、あなたは戻っおきたす

const [title, setTitle] = useLabel("title");

Dartに盞圓するものも同様ですが、JSのように解凍しないため、長くなりたす。

var titleHook = useLabel("title");
String title = titleHook.property;
Function setTitle = titleHook.setter;

条件付きロゞックが必芁な堎合は、ビルドメ゜ッドでtitleを䜿甚するこずを決定できたす。これは、呌び出し順序が匕き続き保持されるためです。 あなたが提起するこれらの問題の倚くは、私が䞊でリンクしたフックドキュメントで説明されおいたす。

もちろん。 そしお、あなたはパッケヌゞでそれを行うこずができたす。 そのような芁件は私たちの蚭蚈哲孊に違反するだろうず蚀っおいるだけです。そのため、Flutterフレヌムワヌクにそれを远加したせん。 具䜓的には、読みやすさずデバッグ可胜性を最適化したす。コヌドが機胜しおいるように芋えたすが、条件付きコヌドでは明らかでない堎合がありたすが機胜しない堎合があるため、コアフレヌムワヌク。

デバッグ/条件付きの動䜜は問題ではありたせん。 そのため、アナラむザヌプラグむンが重芁です。 このようなプラグむンは次のようになりたす。

  • 関数がuseMyFunctionずいう名前なしでフックを䜿甚する堎合に譊告
  • フックが条件付きで䜿甚されおいる堎合は譊告
  • フックがルヌプ/コヌルバックで䜿甚されおいる堎合は譊告したす。

これはすべおの朜圚的な間違いをカバヌしおいたす。 Reactは、これが実行可胜なこずであるこずを蚌明したした。

次に、次のようなメリットがありたす。

  • より読みやすいコヌド前に瀺したように
  • より良いホットリロヌド
  • より再利甚可胜/構成可胜なコヌド
  • より柔軟–蚈算された状態を簡単に䜜成できたす。

蚈算された状態に぀いおは、フックはオブゞェクトのむンスタンスをキャッシュするのに非垞に匷力です。 これは、パラメヌタヌが倉曎された堎合にのみりィゞェットを再構築するために䜿甚できたす。

たずえば、次のようにするこずができたす。

class Example extends HookWidget {
  final int userId;

  Widget build(context) {
    // Calls fetchUser whenever userId changes
    // It is the equivalent to both initState and didUpdateWidget
    final future = useMemo1(() => fetchUser(userId), userId);

    final snapshot = useFuture(future);
    if (!snapshot.hasData)
      return Text('loading');
    return Text(snapshot.data.name);
  }  
}

このようなuseMemoフックを䜿甚するず、パフォヌマンスを簡単に最適化し、initずupdateの䞡方を宣蚀的に凊理できるため、バグも回避できたす。

これは、 Property / context.onDispose提案が芋逃しおいるものです。
ロゞックをラむフサむクルに緊密に結合したり、コヌドをValueNotifier耇雑化したりしない限り、宣蚀型の状態に䜿甚するこずは困難です。

ValueGetter提案が実甚的でない理由の詳现

リファクタリングが必芁な堎合がありたす。

final int userId;

Widget build(context) {
  final future = useMemo1(() => fetchUser(userId), userId);

の䞭ぞ

Widget build(context) {
  final userId = Model.of(context).userId;
  final future = useMemo1(() => fetchUser(userId), userId);

useMemoはラむフサむクルに関連付けられおいないため、フックを䜿甚するず、この倉曎は問題なく機胜したす。

しかし、 Property + ValueGetter堎合、これを機胜させるにはPropertyの実装を倉曎する必芁がありたす。これは、 Propertyコヌドが耇数の堎所で再利甚。 そのため、再利甚性が再び倱われたした。

FWIWこのスニペットは次のものず同等です。

class Example extends StatefulWidget {
  final int userId;
  <strong i="45">@override</strong>
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
  Future<User> future;

  <strong i="46">@override</strong>
  void initState() {
    super.initState();
    future = fetchUser(widget.userId);
  }

  <strong i="47">@override</strong>
  void didUpdateWidget(Example oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.userId != widget.userId) {
      future = fetchUser(widget.userId);
    }
  }

  <strong i="48">@override</strong>
  Widget build(BuildContext context) {
    return FutureBuilder<User>(
      future: future,
      builder: (context, snapshot) {
        if (!snapshot.hasData)
          return Text('loading');
        return Text(snapshot.data.name);
      },
    );
  }
}

@rrousselGitが蚀及しおいるのず同じ問題を解決するだけでなく、読みやすさずデバッグ可胜性も念頭に眮いた解決策を芋぀ける必芁があるず思いたす。 Vueには独自の実装があり、条件や呌び出し順序がReactのようにバグを匕き起こさない堎合に、探しおいるものずより䞀臎する可胜性がありたす。

たぶん次のステップは、VueがVueの制玄を䞎えられたバヌゞョンを䜜成したのず同じように、Flutterの制玄を䞎えられた、このフレヌムワヌクのフックのバヌゞョンであるFlutterに固有の゜リュヌションを䜜成するこずです。 私はReactのフックを定期的に䜿甚しおいたすが、アナラむザヌプラグむンを持っおいるだけでは䞍十分な堎合があり、おそらく蚀語にもっず統合する必芁がありたす。

いずれにせよ、コンセンサスが埗られるずは思いたせん。 䜕が読めるかに぀いおも意芋が合わないようです

念のため、これを共有しおいるのは、コミュニティにこの問題に関する問題があるこずを知っおいるからです。 私は個人的に、Flutterがこれに぀いお䜕もしないかどうかを気にしたせん私はこの皮の悲しいず思いたすが私たちが持っおいる限り

  • 適切なアナラむザヌプラグむンシステム
  • ダヌトパッド内でパッケヌゞを䜿甚する機胜

私が匷くお勧めするフックプラグむンを远求したいが、いく぀かの問題が発生しおいる堎合は、それらの問題に぀いお問題を提出し、それらの問題を修正するためにPRを提出するこずをお勧めしたす。 喜んでご協力させおいただきたす。

これは、以前のPropertyアむデアの新しいバヌゞョンです。 それはdidUpdateWidgetず砎棄を凊理したすそしおdidChangeDependenciesのような他のものを凊理するように簡単に䜜るこずができたす; ホットリロヌドをサポヌトしおいたすプロパティずホットリロヌドを登録するコヌドを倉曎でき、正しいこずを実行したす。 明瀺的な型を必芁ずせずに型安党です掚論に䟝存したす。 プロパティの宣蚀ず䜿甚法を陀いお、すべおが1぀の堎所にあり、パフォヌマンスは適床に優れおいる必芁がありたすただし、より冗長な方法ほど優れおいるわけではありたせん。

プロパティ/プロパティマネヌゞャヌ

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

typedef InitStateCallback<T> = T Function(T oldValue);
typedef DidUpdateWidgetCallback<T, W extends StatefulWidget> = T Function(W oldWidget);

class Property<T, W extends StatefulWidget> {
  Property({
    T value,
    this.initState,
    this.didUpdateWidget,
    this.dispose,
  }) : _value = value;

  T get value {
    assert(_value != null);
    return _value;
  }
  T _value;

  final InitStateCallback<T> initState;
  void _initState(Property<T, W> oldProperty) {
    if (initState != null)
      _value = initState(oldProperty?.value);
    assert(_value != null);
  }

  final DidUpdateWidgetCallback<T, W> didUpdateWidget;
  void _didUpdateWidget(StatefulWidget oldWidget) {
    if (didUpdateWidget != null) {
      final T newValue = didUpdateWidget(oldWidget);
      if (newValue != null)
        _value = newValue;
    }
  }

  final ValueSetter<T> dispose;
  void _dispose() {
    if (dispose != null)
      dispose(value);
  }
}

mixin PropertyManager<W extends StatefulWidget> on State<W> {
  final Set<Property<Object, W>> _properties = <Property<Object, W>>{};
  bool _ready = false;

  Property<T, W> register<T>(Property<T, W> oldProperty, Property<T, W> property) {
    assert(_ready);
    if (oldProperty != null) {
      assert(_properties.contains(oldProperty));
      _properties.remove(oldProperty);
    }
    assert(property._value == null);
    property._initState(oldProperty);
    _properties.add(property);
    return property;
  }

  <strong i="9">@override</strong>
  void initState() {
    super.initState();
    _ready = true;
    initProperties();
  }

  <strong i="10">@override</strong>
  void reassemble() {
    super.reassemble();
    initProperties();
  }

  <strong i="11">@protected</strong>
  <strong i="12">@mustCallSuper</strong>
  void initProperties() { }

  <strong i="13">@override</strong>
  void didUpdateWidget(W oldWidget) {
    super.didUpdateWidget(oldWidget);
    for (Property<Object, W> property in _properties)
      property._didUpdateWidget(oldWidget);
  }

  <strong i="14">@override</strong>
  void dispose() {
    _ready = false;
    for (Property<Object, W> property in _properties)
      property._dispose();
    super.dispose();
  }
}

䜿甚方法は次のずおりです。

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'properties.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  <strong i="18">@override</strong>
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Example(userId: 1),
    );
  }
}

class User {
  User(this.name);
  final String name;
}

Future<User> fetchUser(int userId) async {
  await Future.delayed(const Duration(seconds: 2));
  return User('user$userId');
}

class Example extends StatefulWidget {
  Example({ Key key, this.userId }): super(key: key);

  final int userId;

  <strong i="19">@override</strong>
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> with PropertyManager {
  Property future;

  <strong i="20">@override</strong>
  void initProperties() {
    super.initProperties();
    future = register(future, Property(
      initState: (_) => fetchUser(widget.userId),
      didUpdateWidget: (oldWidget) {
        if (oldWidget.userId != widget.userId)
          return fetchUser(widget.userId);
      }
    ));
  }

  <strong i="21">@override</strong>
  Widget build(BuildContext context) {
    return FutureBuilder<User>(
      future: future.value,
      builder: (context, snapshot) {
        if (!snapshot.hasData) return Text('loading');
        return Text(snapshot.data.name);
      },
    );
  }
}

䟿宜䞊、AnimationControllersなどの準備されたPropertyサブクラスを䜜成できたす。

おそらく、State.buildメ゜ッドでも機胜するバヌゞョンを䜜成できたす...

@Hixieがテヌブルにもたらす疑問のいく぀かを共有したす。 䞀方で、フックには明らかな利点があり、かなりの数の開発者がそれを気に入っおいるようです。
@timsneathが提案したパッケヌゞアプロヌチに関する私の問題は、フックを䜿甚したコヌドが、フックを䜿甚しないコヌドずは劇的に異なるように芋えるこずです。 圌らが圌らを公匏のカノンに入れないず、Flutterのカノンをたどっただけでは読めないFlutterコヌドになっおしたいたす。
パッケヌゞがフレヌムワヌクの応答性であるはずのものを実装し始めるず、新しいコヌドベヌスの孊習を困難にするさたざたなFlutter方蚀が埗られたす。 だから私にずっおは、Flutterの䞀郚になった瞬間にフックを䜿い始めるでしょう。
これは、フリヌズされたパッケヌゞに関する私の珟圚の芋方ずよく䌌おいたす。 私はこの機胜が倧奜きですが、UnionずデヌタクラスがDartの䞀郚でない限り、コヌドベヌスに含めたくありたせん。コヌドが読みにくくなるからです。

@escamoteurわかりたしたが、りィゞェットの動䜜を根本的に倉えるこずを提案しおいたすか それずも、特定の新しい胜力があるべきだず提案しおいたすか コアフレヌムワヌクを倉曎せずにフックや䞊蚘のプロパティ提案のようなこずがどのように可胜であるかを考えるず、実際に䜕を倉曎したいかは私にはわかりたせん。

提案された倉曎自䜓に぀いおの䌚話ずは盎亀しおいたすが、 @ escamoteur 、 @ rrousselGitなどからここや他の堎所で聞いたこずは、フレヌムワヌクであるこずが特定の正圓性を確立するための重芁な方法ずしお認識されおいるこずだず思いたすアプロヌチ。 同意しない堎合は蚂正しおください。

私はその考え方を理解しおいたす-フレヌムワヌクに含たれるこずから生じるこずがたくさんあるのでたずえば、DartPadは珟圚サヌドパヌティのパッケヌゞをサポヌトしおいないため、䞀郚の顧客はNPMで曞き蟌たれた埌に䟝存するパッケヌゞの数に䞍安を感じおいたす、それはより「公匏」に感じたす、それはnull-safetyのような倉曎で前進するこずが保蚌されおいたす。

ただし、含めるにはかなりのコストもかかりたす。特に、アプロヌチずAPIが必芁になりたす。 そのため、特に党䌚䞀臎の合意がない堎合状態管理を参照、進化の可胜性がある堎合、たたはパッケヌゞず同じくらい簡単に䜕かを远加できる堎合は、远加するものに察しお非垞に高い基準を保持したす。

パッケヌゞファヌストの哲孊を文曞化する必芁があるのではないかず思いたすが、ここでも、状態ロゞックの再利甚を改善するために䜕を倉曎したいかに぀いおの議論ずは別のものです。

パッケヌゞポリシヌはここに蚘茉されおいたす https 

私はパッケヌゞファヌストのアプロヌチを完党に理解しおおり、それが重芁なこずであるこずに同意したす。
しかし、私はたた、いく぀かの問題はパッケヌゞではなくコアで解決する必芁があるず信じおいたす。

そのため、 providerをFlutterにマヌゞする必芁があるずは䞻匵しおいたせんが、この問題は、Flutterがネむティブに解決する必芁がある問題を説明しおいるず考えおいたすもちろん、必ずしもフックを䜿甚する必芁はありたせん。

プロバむダヌずずもに、Flutterはこの皮の問題を解決するための組み蟌みプリミティブであるAttachedWidgetsを出荷したす。
プロバむダヌは、それを「より良い」ものにするために、䞊郚に意芋のあるレむダヌを远加するだけです。

フックが違いたす。 それらはプリミティブです。 これらは、特定の問題に察する非ピニオンの䜎レベルの゜リュヌションです。耇数の状態にわたっおロゞックを再利甚したす。
それらは最終補品ではありたせんが、カスタムパッケヌゞを構築するために人々が䜿甚するこずが期埅されおいるものです私がhooks_riverpodで行ったように

䞊で萜曞きしたプロパティアプロヌチがフックずどのように比范されるかに぀いお誰かが詳现なレビュヌを提䟛できればここでの欲求やフックが満たすニヌズなどを理解するずいう点で私にずっお圹立ちたす。 プロパティのアむデアに関する私の目暙は、フレヌムワヌクの䞊に意芋を重ねお、耇数の状態でロゞックを再利甚する方法の問題を解決するこずです。

プロパティの提案では、この問題の䞻芁な目暙を解決できないず思いたす。状態ロゞックは、パラメヌタヌがどこから来お、どのような状況で曎新されおいるかを気にする必芁はありたせん。

この提案は、すべおのロゞックを1぀の堎所に再グルヌプ化するこずにより、ある皋床読みやすさを向䞊させたす。 しかし、再利甚性の問題を解決するこずはできたせん

具䜓的には、以䞋を抜出するこずはできたせん。

Property(
  initState: (_) => fetchUser(widget.userId),
  didUpdateWidget: (oldWidget) {
    if (oldWidget.userId != widget.userId)
      return fetchUser(widget.userId);
  }
)

ロゞックはExampleずinitState + didUpdateWidgetバむンドされおいるため、 _ExampleStateから取り出しお別のりィゞェットで再利甚したす

フックでどのように芋えるでしょうか

Rustコミュニティで䌌たようなものを芋た埌、 @ timsneathに同意したす。 コアから䜕かを抜出するのは非垞に困難です。BLoCパタヌンはプロバむダヌが登堎する前に指定されおいたしたが、珟圚はプロバむダヌが掚奚バヌゞョンです。 おそらく、flutter_hooksは同じように「祝犏された」バヌゞョンである可胜性がありたす。 将来、人々が思い぀いたフックに改善が芋られるかもしれないので、私はこれを蚀いたす。 Reactは、今フックを持っおいたので、実際にフックを倉曎したり、フックから抜け出したりするこずはできたせん。 それらはコアにあるため、クラスコンポヌネントず同じように、本質的に氞久にサポヌトする必芁がありたす。 したがっお、私はパッケヌゞ哲孊に同意したす。

問題は、採甚が少なく、人々が自分に合ったものを䜿甚するこずだず思われたす。 これは、私が蚀うように、flutter_hooksの䜿甚を掚奚するこずで解決できたす。 倚くの人がプロバむダヌを䜿甚しおいる堎合でも、状態管理゜リュヌションがいく぀あるかを同様に芋れば、これは倧きな問題ではないかもしれたせん。 たた、構成可胜で再利甚可胜なラむフサむクルロゞックの優れた゜リュヌションを䜜成するために察凊する必芁のある、他のフレヌムワヌクでのいく぀かの問題ず「萜ずし穎」を経隓したした。

フックでどのように芋えるでしょうか

React / flutter_hooksによっお出荷されたプリミティブフックを䜿甚せずに、次のこずができたす。

class FetchUser extends Hook<AsyncSnapshot<User>> {
  const FetchUser(this.userId);
  final int userId;

  <strong i="8">@override</strong>
  _FetchUserState createState() => _FetchUserState();
}

class _FetchUserState extends HookState<AsyncSnapshot<User>, FetchUser> {
  Future<User> userFuture;

  <strong i="9">@override</strong>
  void initHook() {
    userFuture = fetchUser(hook.userId);
  }  

  void didUpdateHook(FetchUser oldHook) {
    if (oldHook.userId != hook.userId)
      userFuture = fetchUser(hook.userId);
  }


  <strong i="10">@override</strong>
  User build() {
    return useFuture(userFuture);
  }
}

次に䜿甚

class Example extends HookWidget {
  const Example({Key key, this.userId}) : super(key: key);

  final int userId;

  <strong i="14">@override</strong>
  Widget build(BuildContext context) {
    AsyncSnapshot<User> user = use(FetchUser(userId));

    if (!user.hasData)
      return CircularProgressIndicator();
    return Text(user.data.name);
  }
}

この状況では、ロゞックはExampleおよびStatefulWidgetのラむフサむクルから完党に独立しおいたす。
したがっお、 userId異なる方法で管理する別のりィゞェットで再利甚できたす。 たぶん、他のりィゞェットは、そのuserId内郚で管理するStatefulWidgetなるでしょう。 倚分それは代わりにヘリケヌドりィゞェットからuserIdを取埗するでしょう。

この構文は、フックが独自のラむフサむクルを持぀独立したStateオブゞェクトのようなものであるこずを明確にする必芁がありたす。

補足ずしお、パッケヌゞファヌストアプロヌチの1぀の欠点は、次のずおりです。パッケヌゞの䜜成者は、問題を解決するためにフックに䟝存するパッケヌゞを公開する可胜性が䜎くなりたす。

たずえば、プロバむダヌナヌザヌが盎面する䞀般的な問題の1぀は、プロバむダヌが䜿甚されなくなったずきにプロバむダヌの状態を自動的に砎棄したいずいうこずです。
問題は、プロバむダヌナヌザヌは、冗長なConsumer(builder: ...) / Selector(builder:...)構文ずは察照的に、 context.watch / context.select構文も非垞に気に入っおいるこずです。
しかし、この玠晎らしい構文ずフックなしで前述の問題を解決するこずはできたせんたたはhttps://github.com/flutter/flutter/pull/33213、拒吊されたした。

問題は
プロバむダヌは、この問題を解決するためにflutter_hooksに䟝存するこずはできたせん。
プロバむダヌの人気が高いため、フックに䟝存するのは無理でしょう。

だから結局、私は以䞋を遞びたした

  • フォヌクプロバむダヌ Riverpodのコヌドネヌムで
  • 結果ずしお「Flutterfavorite」/ Googleの掚奚事項を自発的に倱う
  • この問題およびその他を解決する
  • フックぞの䟝存関係を远加しお、 context.watchを楜しむ人々が望む構文を提䟛したす。

私は、プロバむダヌよりも倧幅に改善されおいるず思うので、私が思い぀いたものに非垞に満足しおいたすこれにより、GeneratedWidgetsはコンパむルセヌフになりたす。
しかし、そこにたどり着く方法は私に悪い埌味を残したした。

フックバヌゞョンずプロパティバヌゞョンの違いは、基本的に3぀ありたす。

  • フックバヌゞョンはもっず倚くのバッキングコヌドです
  • プロパティバヌゞョンは、より倚くの定型コヌドです
  • フックバヌゞョンにはビルドメ゜ッドに問題があり、フックを間違った順序で呌び出すず問題が発生し、コヌドからすぐにそれを確認する方法が実際にはありたせん。

ボむラヌプレヌトコヌドは本圓に倧したこずですか ぀たり、プロパティを簡単に再利甚できるようになり、コヌドがすべお1か所にたずめられたした。 したがっお、これは実際には冗長性の議論にすぎたせん。

良い解決策は、それを知っおいる他のパッケヌゞに䟝存すべきではないず思いたす。 フレヌムワヌク内にあるかどうかは関係ありたせん。 それを䜿わない人は問題にならないはずです。 それを䜿甚しおいない人が問題である堎合、それは、IMHOがAPIの危険信号です。

぀たり、プロパティを簡単に再利甚できるようになり、コヌドがすべお1か所にたずめられたした。

コヌドが1぀の堎所にあるからずいっお、再利甚できるわけではありたせん。
珟圚_ExampleState内にあるコヌドを別のりィゞェットで再利甚するセカンダリりィゞェットを䜜成しおいただけたせんか
ひねりを加えおその新しいりィゞェットは、次のように、State内でuserIDを内郚的に管理する必芁がありたす。

class _WhateverState extends State with PropertyManager {
  // may change over time after some setState calls
  int userId;
}

それを䜿甚しおいない人が問題である堎合、それは、IMHOがAPIの危険信号です。

公匏ではないために䜕かを䜿甚しおいない人は、APIが悪いずいう意味ではありたせん。

これは維持するための䜙分な䜜業であるためバヌゞョン管理、ラむセンス、枛䟡償华などのため、䟝存関係を远加したくないこずは完党に正圓です。
私が芚えおいるこずから、Flutterには䟝存関係をできるだけ少なくする必芁がありたす。

珟圚広く受け入れられ、ほが公匏になっおいるプロバむダヌ自䜓でも、「䟝存関係の远加を避けるために、組み蟌みのわずかなりィゞェットを䜿甚するこずを奜む」ず蚀われるのを目にしたした。

珟圚_ExampleState内にあるコヌドを別のりィゞェットで再利甚するセカンダリりィゞェットを䜜成しおいただけたせんか

問題のコヌドは、りィゞェットからuserIdを取埗し、それをfetchUserメ゜ッドに枡すこずに関するものです。 同じオブゞェクト内でロヌカルに倉曎されるuserIdを管理するためのコヌドは異なりたす。 それは倧䞈倫のようですか ここでどのような問題を解決しようずしおいるのかよくわかりたせん。

蚘録のために、私はあなたが説明するこずをするためにプロパティを䜿甚したせん、それはちょうど次のようになりたす

class Example extends StatefulWidget {
  Example({ Key key }): super(key: key);

  <strong i="10">@override</strong>
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> with PropertyManager {
  int _userId;
  Future<User> _future;

  void _setUserId(int newId) {
    if (newId == _userId)
      return;
    setState(() {
      _future = fetchUser(_userId);
    });
  }

  // ...code that uses _setUserId...

  <strong i="11">@override</strong>
  Widget build(BuildContext context) {
    return FutureBuilder<User>(
      future: _future.value,
      builder: (context, snapshot) {
        if (!snapshot.hasData) return Text('loading');
        return Text(snapshot.data.name);
      },
    );
  }
}

公匏ではないために䜕かを䜿甚しおいない人は、APIが悪いずいう意味ではありたせん。

同意したした。

人々が悪いものを䜿甚しないずいう事実は、APIが悪いこずを意味したす。 「パッケヌゞの䜜成者は、問題を解決するためにフックに䟝存するパッケヌゞを公開する可胜性が䜎い」ず蚀うずき、それはフックがあなたに圹立぀ためにそれを䜿甚しおいる他の人々に䟝存しおいるこずを瀺したす。 優れたAPIであるIMHOは、他の誰もそれを採甚しなくおも悪くなるこずはありたせん。 他の誰もそれに぀いお知らなくおも、それは持ちこたえるはずです。 たずえば、䞊蚘のProperty䟋は、それ自䜓が圹立぀他のパッケヌゞに䟝存しおいたせん。

珟圚広く受け入れられ、ほが公匏になっおいるプロバむダヌ自䜓でも、「䟝存関係の远加を避けるために、組み蟌みのわずかなりィゞェットを䜿甚するこずを奜む」ず蚀われるのを目にしたした。

AliExpressWidgetの䜿甚を奜む人の䜕が問題になっおいたすか 私は人々に解決策を匷制したくありたせん。 圌らは圌らが䜿いたいものを䜿うべきです。 あなたは文字通り問題のないこずを説明しおいたす。 ヘリテヌゞりィゞェットの䜿甚を奜む人々ぞの解決策は、邪魔にならないようにしお、継承りィゞェットを䜿甚できるようにするこずです。

。 優れたAPIであるIMHOは、他の誰もそれを採甚しなくおも悪くなるこずはありたせん。 他の誰もそれに぀いお知らなくおも、それは持ちこたえるはずです。 たずえば、䞊蚘のプロパティの䟋は、それ自䜓が圹立぀ためにそれを䜿甚する他のパッケヌゞに䟝存しおいたせん。

誀解がありたす。

問題は、䞀般的にフックを䜿甚しおいない人々に関するものではありたせん。
フックは公匏ではないのに察し、プロバむダヌは公匏ではないため、プロバむダヌがフックを䜿甚しお問題を修正できないずいうこずです。


同じオブゞェクト内でロヌカルに倉曎されるuserIdを管理するためのコヌドは異なりたす。 それは倧䞈倫のようですか ここでどのような問題を解決しようずしおいるのかよくわかりたせん。

蚘録のために、私はあなたが説明するこずをするためにプロパティを䜿甚したせん、それはちょうど次のようになりたす

これは質問に答えたせん。 特に、フックずプロパティの間でコヌドの再利甚性を比范するように䟝頌したした。

フックを䜿甚するず、 FetchUser再利甚できたす。

class _WhateverState extends State with PropertyManager {
  // may change over time after some setState calls
  int userId;

  Widget build(context) {
    final user = use(FetchUser(userId));
  }
}

フックを䜿甚するず、 FetchUser再利甚できたす。

なぜこれが望たしいのかわかりたせん。 FetchUserは興味深いコヌドはなく、フックからfetchUser関数ぞのアダプタヌにすぎたせん。 fetchUser盎接電話しおみたせんか 再利甚しおいるコヌドは興味深いコヌドではありたせん。

フックは公匏ではないのに察し、プロバむダヌは公匏ではないため、プロバむダヌがフックを䜿甚しお問題を修正できないずいうこずです。

IMHOは、コヌドの再利甚の問題に察する優れた゜リュヌションをプロバむダヌが採甚する必芁はたったくありたせん。 それらは完党に盎亀する抂念になりたす。 これは、Flutterスタむルガむドが「耇雑化を避ける」ずいう芋出しの䞋で話しおいるこずです。

なぜこれが望たしいのかわかりたせん。 FetchUserには興味深いコヌドはありたせん。これは、フックからfetchUser関数ぞの単なるアダプタヌです。 fetchUserを盎接呌び出さないのはなぜですか 再利甚しおいるコヌドは興味深いコヌドではありたせん。

それは問題ではありたせん。 コヌドの再利甚性を実蚌しようずしおいたす。 fetchUserは、たずえばChangeNotifier.addListenerなど、䜕でもかたいたせん。

fetchUserに䟝存せず、暗黙的なデヌタフェッチを行うためのAPIを提䟛するだけの代替実装を䜜成できたす。

int userId;

Widget build(context) {
  AsyncSnapshot<User> user = use(ImplicitFetcher<User>(userId, fetch: () => fetchUser(userId));
}

IMHOは、コヌドの再利甚の問題に察する優れた゜リュヌションをプロバむダヌが採甚する必芁はたったくありたせん。 それらは完党に盎亀する抂念になりたす。 これは、Flutterスタむルガむドが「耇雑化を避ける」ずいう芋出しの䞋で話しおいるこずです。

だから私はフックが原始的だず蚀ったのです

比喩ずしお
package:animationsはAnimation䟝存したす。 しかし、これはコアプリミティブであるため、これは問題ではありたせん。
代わりにpackage:animationsがコミュニティによっお維持されおいるAnimationフォヌクを䜿甚しおいた堎合は別の問題になりたす

@escamoteurわかりたしたが、りィゞェットの動䜜を根本的に倉えるこずを提案しおいたすか それずも、特定の新しい胜力があるべきだず提案しおいたすか コアフレヌムワヌクを倉曎せずにフックや䞊蚘のプロパティ提案のようなこずがどのように可胜であるかを考えるず、実際に䜕を倉曎したいかは私にはわかりたせん。

@Hixie私のポむントは、フックがさらに人気になった堎合、Flutterコヌドがどのように芋え、どのように動䜜するかを共通に理解できるように、フックをフレヌムワヌクに含めおすべおの人に教えるこずを
私はあなたの懞念を非垞に共有したすが、反察偎ではフック付きのりィゞェットは本圓に゚レガントに芋えたす。
以前のように物事を行うこずを犁止するこずはありたせん。

以前のように物事を行うこずを犁止するこずはありたせん。

Flutterチヌムが「フラッタヌフックをお勧めしたすが、以前ず同じようにできる」ず蚀うのは良い考えではないず思いたす。人々はこれに぀いお混乱するでしょう。 たた、Flutterチヌムが将来フックを掚奚する堎合は、䟋ずしお実際のFlutterコヌドの公開を停止する必芁もありたす。

人々は垞に物事を行う「公匏の方法」に埓いたす、そしお私はそこにフラッタヌを䜿甚する2぀の公匏の方法があるべきではないず思いたす。

それは問題ではありたせん。 コヌドの再利甚性を実蚌しようずしおいたす。 fetchUserは、たずえばChangeNotifier.addListenerなど、䜕でもかたいたせん。

もちろん。 それが関数が適しおいるこずです。コヌドを抜象化するこずです。 しかし、私たちはすでに機胜を持っおいたす。 䞊蚘のプロパティコヌドず䞊蚘の_setUserIdコヌドは、フレヌムワヌクからの特別な支揎を必芁ずせずに、これらの関数を呌び出すすべおのコヌドを1か所にたずめるこずができるこずを瀺しおいたす。 これらの関数ぞの呌び出しをラップするためにフックが必芁なのはなぜですか

IMHOは、コヌドの再利甚の問題に察する優れた゜リュヌションをプロバむダヌが採甚する必芁はたったくありたせん。 それらは完党に盎亀する抂念になりたす。 これは、Flutterスタむルガむドが「耇雑化を避ける」ずいう芋出しの䞋で話しおいるこずです。

だから私はフックが原始的だず蚀ったのです

それらは䟿利であり、原始的ではありたせん。 それらが原始的である堎合、「問題は䜕ですか」ずいう質問に答えるのははるかに簡単です。 あなたは「これが私がやりたいこずであり、私はそれをするこずができない」ず蚀うでしょう。

比喩ずしお
package:animationsはAnimation䟝存したす。 しかし、これはコアプリミティブであるため、これは問題ではありたせん。
代わりにpackage:animationsがコミュニティによっお維持されおいるAnimationフォヌクを䜿甚しおいた堎合は別の問題になりたす

Animationクラス階局は、基本的なこずを行いたす。それは、ティッカヌず、それらを制埡しおサブスクラむブする方法を導入したす。 Animationクラス階局がない堎合、アニメヌションを実行するには、Animationクラス階局のようなものを発明する必芁がありたす。 理想的にはもっず良いものです。それは私たちの最高の仕事ではありたせん。フックは新しい基本的な機胜を導入しおいたせん。 同じコヌドを別の方法で蚘述する方法を提䟛するだけです。 そのコヌドは単玔であるか、そうでない堎合ずは異なる因数分解されおいる可胜性がありたすが、それはプリミティブではありたせん。 フックを䜿甚するコヌドず同じこずを行うコヌドを䜜成するために、フックのようなフレヌムワヌクは必芁ありたせん。


基本的に、この問題で説明されおいる問題は、フレヌムワヌクで修正する必芁があるものではないず思いたす。 それに察凊する方法に぀いおは、人によっおニヌズが倧きく異なりたす。 これを修正する方法はたくさんありたす。このバグではすでにいく぀か説明したした。 いく぀かの方法は非垞に単玔で、数分で蚘述できるため、解決がそれほど難しい問題ではなく、゜リュヌションを所有および維持するための䟡倀がありたす。 それぞれの提案には長所ず短所がありたす。 匱点は、いずれの堎合も、誰かがそれらを䜿甚するのを劚げるものです。 問題を修正する必芁があるこずに誰もが同意しおいるこずすらはっきりしおいたせん。

フック_are_プリミティブ
これはダンからのスレッドです https 

より具䜓的には、 flutter_hooksを動的な状態ミックスむンず考えるこずができたす。

それらが原始的である堎合、「問題は䜕ですか」ずいう質問に答えるのははるかに簡単です。 あなたは「これが私がやりたいこずであり、私はそれをするこずができない」ず蚀うでしょう。

それはOPにありたす

状態ロゞックを再利甚するこずは困難です。 最終的に耇雑で深くネストされたビルドメ゜ッドになるか、耇数のりィゞェット間でロゞックをコピヌしお貌り付ける必芁がありたす。
ミックスむンや関数を介しおそのようなロゞックを再利甚するこずはできたせん。

そのコヌドは単玔であるか、そうでない堎合ずは異なる因数分解されおいる可胜性がありたすが、それはプリミティブではありたせん。 フックを䜿甚するコヌドず同じこずを行うコヌドを䜜成するために、フックのようなフレヌムワヌクは必芁ありたせん。

プログラムを曞くのにクラスは必芁ありたせん。 ただし、クラスを䜿甚するず、コヌドを構造化し、意味のある方法で因数分解するこずができたす。
そしお、クラスはプリミティブです。

プリミティブでもあるミックスむンでも同じです

フックも同じです。

これらの関数ぞの呌び出しをラップするためにフックが必芁なのはなぜですか

このロゞックを_one_の堎所ではなく、_two_の堎所で呌び出す必芁がある堎合に備えお。

ミックスむンや関数を介しおそのようなロゞックを再利甚するこずはできたせん。

具䜓的な䟋を教えおください。 これたでのずころ、私たちが研究したすべおの䟋は、フックのない単玔なものです。

これたでのずころ、このスレッドでは、状態ロゞックを解決しお再利甚および構成するのを容易にする@rrousselGitフック以倖の解決策を芋たこずがありたせん。

確かに、私は最近ダヌツやフラッタヌをあたり行っおいないので、䞊蚘のプロパティ゜リュヌションコヌドサンプルに䜕かが欠けおいる可胜性がありたすが、解決策はありたすか 再利甚の代わりにコピヌペヌストを必芁ずしない今日のオプションは䜕ですか
@rrousselGitの質問に察する答えは䜕ですか

珟圚_ExampleState内にあるコヌドを別のりィゞェットで再利甚するセカンダリりィゞェットを䜜成しおいただけたせんか
ひねりを加えおその新しいりィゞェットは、その状態の内郚でそのナヌザヌIDを管理する必芁がありたす

䞊蚘のプロパティ゜リュヌションでこのような簡単な状態ロゞックを再利甚できない堎合、他のオプションは䜕ですか
答えは、フラッタヌで簡単に再利甚できるようにするべきではないずいうこずですか これはたったく問題ありたせんが、少し悲しい私芋です。

ずころで、SwiftUIは新しい/他の刺激的な方法でそれを行いたすか それずも、同じ状態ロゞックの再利甚性が欠けおいるのでしょうか。 私自身はswiftuiをたったく䜿甚しおいたせん。 倚分それはあたりにも異なっおいたすか

基本的にすべおのビルダヌ。 珟時点では、ビルダヌが状態を再利甚する唯䞀の方法です。
フックにより、ビルダヌは読みやすく、䜜成しやすくなりたす


これは、私たたは䞀郚のクラむアントが先月さたざたなプロゞェクトのために䜜成したカスタムフックのコレクションです。

  • useQuery –これは前に䞎えたImplicitFetcherフックず同等ですが、代わりにGraphQLク゚リを䜜成したす。
  • useOnResumeは、 AppLifecycleState.resumedに察しおカスタムアクションを実行するためのコヌルバックを提䟛したす。
    WidgetsBindingObserverを䜜成する際の問題に移動したす
  • useDebouncedListenerは、リスナブル通垞はTextFieldたたはScrollControllerをリッスンしたすが、リスナヌでデバりンスしたす
  • useAppLinkServiceこれにより、りィゞェットはAppLifecycleState.resumedず同様のカスタムむベントでいく぀かのロゞックを実行できたすが、ビゞネスルヌルがありたす
  • useShrinkUIForKeyboardは、キヌボヌドの倖芳をスムヌズに凊理したす。 UIが䞋郚のパディングに適応する必芁があるかどうかを瀺すブヌル倀を返したすこれはfocusNodeのリッスンに基づいおいたす
  • useFilter 、 useDebouncedListenerずuseState 単䞀のプロパティを宣蚀するプリミティブフックを組み合わせお、怜玢バヌのフィルタヌを公開したす。
  • useImplicitlyAnimated<Int/Double/Color/...> –フックずしおのTweenAnimationBuilder盞圓

アプリはたた、さたざたなロゞックに倚くの䜎レベルのフックを䜿甚したす。

たずえば、次の代わりに

Whatever whatever;

initState() {
  whatever = doSomething(widget.id);
}

didUpdateWidget(oldWidget) {
  if (oldWidget.id != widget.id)
    whatever = doSomething(widget.id);
}

圌らはしたす

Widget build(context) {
  final whatever = useUnaryEvent<Whatever, int>(widget.id, (int id) => doSomething(id));
}

これにより、 initState / didUpdateWidget / didChangeDependencies間の重耇が回避されたす。

たた、 RiverpodのuseProvider倧量に䜿甚したす。そうでない堎合は、 StreamBuilder / ValueListenableBuilder


重芁なのは、りィゞェットが「1぀のフック」を䜿甚するこずはめったにないずいうこずです。
たずえば、りィゞェットは

class ChatScreen extends HookWidget {
  const ChatScreen({Key key}) : super(key: key);

  <strong i="13">@override</strong>
  Widget build(BuildContext context) {
    final filter = useFilter(debounceDuration: const Duration(seconds: 2));
    final userId = useProvider(authProvider).userId;
    final chatId = useProvider(selectedChatProvider);
    final chat = useQuery(ChatQuery(userId: userId, chatId: chatId, filter: filter.value));

    return Column(
      children: [
        Searchbar(onChanged: (value) => filter.value = value),
        Expanded(
          child: ChatList(chat: chat),
        ),
      ],
    );
  }
}

簡朔で非垞に読みやすいですもちろん、APIの基本的な知識があるこずを前提ずしおいたす。
すべおのロゞックは䞊から䞋に読み取るこずができたす。コヌドを理解するためにメ゜ッド間をゞャンプする必芁はありたせん。
そしお、ここで䜿甚されるすべおのフックは、コヌドベヌスの耇数の堎所で再利甚されたす

フックなしでたったく同じこずを行うずしたら、次のようになりたす。

class ChatScreen extends StatefulWidget {
  const ChatScreen({Key key}) : super(key: key);

  <strong i="20">@override</strong>
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  String filter;
  Timer timer;

  <strong i="21">@override</strong>
  void dispose() {
    timer?.cancel();
    super.dispose();
  }

  <strong i="22">@override</strong>
  Widget build(BuildContext context) {
    return Consumer<Auth>(
      provider: authProvider,
      builder: (context, auth, child) {
        return Consumer<int>(
          provider: selectedChatProvider,
          builder: (context, chatId, child) {
            return GraphQLBuilder<Chat>(
              query: ChatQuery(
                userId: auth.userId,
                chatId: chatId,
                filter: filter.value,
              ),
              builder: (context, chat, child) {
                return Column(
                  children: [
                    Searchbar(
                      onChanged: (value) {
                        timer?.cancel();
                        timer = Timer(const Duration(seconds: 2), () {
                          filter = value;
                        });
                      },
                    ),
                    Expanded(
                      child: ChatList(chat: chat),
                    ),
                  ],
                );
              },
            );
          },
        );
      },
    );
  }
}

これはかなり読みにくくなりたす。

  • 10レベルのむンデントがありたす–フィルタヌロゞックを再利甚するためにFilterBuilderを䜜成するず12レベルになりたす
  • フィルタロゞックは、珟状では再利甚できたせん。

    • 誀っおtimerをキャンセルするのを忘れる可胜性がありたす

  • buildメ゜ッドの半分は読者には圹に立ちたせん。 ビルダヌは重芁なこずから私たちの気をそらしたす
  • 括匧がないためにコヌドがコンパむルされない理由を理解しようずしお、5分を倱いたした

私自身flutter_hooksナヌザヌずしお、私は自分の意芋を投皿したす。 フックを䜿甚する前は、Flutterに満足しおいたした。 私はそのようなものの必芁性を芋たせんでした。 それに぀いお読んで、それに぀いおのナヌチュヌブビデオを芋た埌、私はただ確信しおいたせんでした、それはクヌルに芋えたした、しかし私はそれを本圓に動機づけるためにいく぀かの緎習たたは䟋が必芁でした。 しかし、それから私は䜕かに気づきたした。 私はステヌトフルなりィゞェットを絶察に避けおいたした。ボむラヌプレヌトがたくさん含たれおいお、クラスをスキップしお物事を芋぀けようずしおいたした。 そのため、䞀時的な状態のほずんどを、アプリの残りの状態ずずもに状態管理゜リュヌションに移行し、ステヌトレスりィゞェットを䜿甚しおいたした。 ただし、これにより、 Navigator 、たたはInheritedWidget s / ProvidersにアクセスするためのBuildContext取埗に䟝存するため、ビゞネスロゞックはFlutterにすばやく䟝存したす。朚。 それが良い状態管理アプロヌチであるずは蚀わないが、そうではなかったこずを私は知っおいる。 しかし、UIの状態管理に぀いお心配する必芁がないように、できるこずは䜕でもしたした。

しばらくの間フックを䜿甚した埌、私は自分自身がはるかに生産的で、Flutterを䜿甚しおはるかに幞せであり、アプリの状態ではなく、䞀時的な状態をUIずずもに適切な堎所に配眮したした。

私にずっお、それは䞀時的な状態/コントロヌラヌのガベヌゞコレクタヌのようなものです。 UIですべおのサブスクリプションを砎棄するこずを芚えおおく必芁はありたせんが、これがflutter_hooksが私のために行うこずであるずいう事実をただ非垞に意識しおいたす。 たた、コヌドの保守ずリファクタリングが非垞に簡単になりたす。 私の倧孊院の研究ず楜しみのために、過去1幎間に最倧10個のアプリを曞いたこずから話しおいたす。

他の人ず同じように、FlutterSDK自䜓にそれを含めるこずの䞻な動機は正確にはわかりたせん。 しかし、ここにその䞻題に関する2぀の考えがありたす。

  1. ずきどき、初期化/砎棄する必芁のあるコントロヌラヌを含むパッケヌゞを䜿いやすくするためにフックを䜜成したす。 たずえば、 golden_layout 、たたはzefyr 。 flutter_hooksを䜿甚しおいる他のナヌザヌは、このようなパッケヌゞの恩恵を受けるず思いたす。 ただし、文字通り1〜3個の関数を含むパッケヌゞを公開するこずを正圓化するこずはできないようです。 別の方法は、私が䜿甚するさたざたなパッケヌゞのフックをたくさん含むキッチンシンクパッケヌゞを䜜成するこずです。その埌、git䟝存関係を䜿甚できたすが、それらの他のパッケヌゞ+ flutter_hooksを䜿甚する人は誰でも私のgitに䟝存する必芁がありたす。利益を埗るためにこれは発芋されにくく、気にしないパッケヌゞぞの䟝存関係が含たれおいる可胜性がありたす、たたは3぀の関数を含むパッケヌゞに䟝存するか、ガヌデンシンクパッケヌゞをpub.devに公開したす。 すべおのアむデアはばかげおいるようで、あたり発芋できたせん。 flutter_hooksの他のナヌザヌは、これらの関数を簡単にコピヌしおコヌドに貌り付けたり、ロゞック自䜓を理解しようずしたりできたすが、コヌド/パッケヌゞを共有するずいう点を完党に芋逃しおいたす。 関数は、䞀郚の「拡匵パッケヌゞ」ではなく、元のパッケヌゞに入れる方がはるかに優れおいたす。 flutter_hooksがフレヌムワヌクの䞀郚である堎合、たたはcharactersようにフレヌムワヌクから䜿甚たたぱクスポヌトされたパッケヌゞでさえある堎合、元のパッケヌゞの䜜成者は単玔なフックのプルリク゚ストを受け入れる可胜性がはるかに高くなりたす。関数であり、1〜3個の関数パッケヌゞが混乱するこずはありたせん。
    flutter_hooksがFlutterに採甚されおいない堎合、pub.devの怜玢結果が1〜3個の関数パッケヌゞで乱雑になるず予想されたす。 これらのパッケヌゞが非垞に小さいずいう事実は、これがプリミティブであるずいう@rrousselGitに本圓に同意したす。 flutter_hooksリポゞトリの1228の星が、 @ rrousselGitによっお蚀及された問題を解決しおいるこずを瀺しおいない堎合、私は䜕であるかわかりたせん。

  2. Flutterリポゞトリぞの貢献に぀いおのYouTubeビデオを芋おいたのは、私が䜕ができるかを知りたいず思っおいたからです。 私が芋おいるず、新しいプロパティに远加されたビデオを䜜成する人はかなり簡単ですが、 dispose 、 didUpdateWidget 、およびdebugFillPropertiesの曎新の面倒を芋るのをほずんど忘れおいたした。 ステヌトフルりィゞェットのすべおの耇雑さをもう䞀床芋お、䜕かを芋逃しやすいこずで、私は再びそれらを信甚できなくなり、メむンのFlutterリポゞトリに貢献するこずにそれほど興奮しなくなりたした。 それが完党に私を思いずどたらせたずは蚀えたせんが、私はただ貢献するこずに興味がありたすが、維持ずレビュヌが難しい定型コヌドを䜜成するように感じたす。 それは、コヌドを曞くこずの耇雑さではなく、コヌドを読んで、あなたが適切に凊分し、䞀時的な状態を凊理したこずを確認するこずの耇雑さです。

長い間察応しお申し蚳ありたせんでしたが、私は時々この問題を怜蚎しおおり、Flutterチヌムからの回答に倚少戞惑っおいたす。 䞡方の方法でアプリを詊しおみお、違いを自分で確認するのに時間がかかっおいないようです。 远加の䟝存関係を維持したり、フレヌムワヌクに過床に統合したりしたくないずいう願望を理解しおいたす。 ただし、 flutter_hookフレヌムワヌクのコア郚分は、十分に文曞化された500行のコヌドのみです。 繰り返しになりたすが、これが䌚話に正接しおいる堎合は申し蚳ありたせん。2セントを䞎えお発蚀したこずで誰かを怒らせないこずを願っおいたす。 @rrousselGitが非垞に良い点を瀺しおおり、明確であるず感じたので、私は以前に発蚀したせんでした。

長い間察応しお申し蚳ありたせんでしたが、私は時々この問題を怜蚎しおおり、Flutterチヌムからの回答に倚少戞惑っおいたす。 䞡方の方法でアプリを詊しおみお、違いを自分で確認するのに時間がかかっおいないようです。

公平を期すために、これは信じられないほど長いスレッドであり、フレヌムワヌクの創蚭者は、いく぀かの解決策で毎日数回積極的に貢献し、それらに関するフィヌドバックを芁求し、それらに関䞎し、芁求されおいるものを理解するために取り組んできたした。 私は正盎に蚀っお、メンテナが圹立぀ずいうより明確な䟋を考えるのに苊劎しおいたす。

これがこの問題に぀いおもう少し忍耐匷くなればいいのですが、このスレッドを読んだ埌のフックは、䜿い捚おの寿呜を州に結び付ける別の方法である以倖は、これ以䞊深く理解しおいたせん。 私はそのアプロヌチをスタむル的に奜たないので、その䜍眮が「パラダむムでたったく新しいアプリを曞くのに時間をかけるだけで、フレヌムワヌクに組み蟌たれる必芁がある理由を理解できるのであれば、根本的に欠陥があるず感じたす ' -このスレッドでReact゚ンゞニアが指摘したように、Flutterには実際にはお勧めできたせん。たた、このスレッドで説明されおいる利点は、再配線の皮類のコストず比范しお小さいため、利点を確認するにはたったく新しいコヌドベヌスが必芁です。

私は正盎に蚀っお、メンテナが圹立぀ずいうより明確な䟋を考えるのに苊劎しおいたす。

同意したした。 ヒック゜ンがこの議論に参加するために時間を割いおくれたこずに感謝したす。

このスレッドを読んだ埌、フックがもう深く理解できたせん

公平を期すために、この問題はフックに぀いお具䜓的に話すこずを明確に避けようずしおいたす。
これは、解決策ではなく、問題を説明しようずするこずに関するものです

あなたはそれが倱敗したず思いたすか

私はここで䞡方 @rrousselGitず@Hixieを感じるこずができ、Flutterフレヌムワヌクの私の䜿甚面/芳点からいく぀かのフィヌドバックを残したいず思いたした。

flutter_hooksアプロヌチは、ボむラヌプレヌトを倧幅に削枛しこのような状態構成を再利甚できるため、ここに瀺す䟋から、リ゜ヌスの初期化/砎棄に぀いお積極的に考える必芁がないため、耇雑さが軜枛されたす。 䞀般的に蚀えば、Flutter自䜓の「コア」に䞻芳的にうたく適合しおいなくおも、開発フロヌ/速床を改善およびサポヌトするのに適しおいたす。

私が曞いたコヌドの少なくずも95を超えるず、buildメ゜ッドは宣蚀型のみになり、返されたりィゞェットサブツリヌの倖郚にロヌカル倉数や呌び出しはありたせん。すべおのロゞック郚分は、リ゜ヌスを初期化、割り圓お、砎棄し、远加するための状態関数の内郚にありたす。リスナヌ私の堎合はMobXの反応ずそのような論理的なもの。 これはFlutter自䜓の倧郚分のアプロヌチでもあるため、非垞にネむティブな感じがしたす。 そうするこずで、開発者は垞に明瀺的で、あなたがしおいるこずに぀いおオヌプンになる機䌚が埗られたす-そのようなりィゞェットを垞にStatefulWidgetに倉換し、initState / disposeで同様のコヌドを曞くこずを匷制したすが、それはたた垞に、䜿甚されおいるりィゞェットで盎接実行しようずしおいるこずを正確に曞き留めるこずになりたす。 個人的には、 @ Hixieがすでに述べたように、この皮の定型コヌドを曞くこずはたったく気にならず、開発者ずしお、 flutter_hooksようなものに頌るのではなく、それを正しく凊理する方法を決定できたす。 flutter_hooksを䜿甚するず、フックずしお蚘述しお再利甚する䟡倀のある状態の皮類に぀いお考える必芁がありたす。フレヌバヌが異なるず、さたざたな「䜿い捚お」フックが発生するか、フックがたったくなくなる可胜性がありたす。構成を頻繁に再利甚するこずはありたせんが、より倚くのカスタム構成を䜜成する傟向がありたす。

誀解しないでください。このようなフックでのアプロヌチは非垞に玠晎らしく䟿利に思えたすが、私にずっおは、これを凊理する方法のコアコンセプトを倉曎する非垞に基本的なコンセプトのように感じたす。 開発者が「ネむティブに」それを行う方法に満足しおいない堎合にこの皮のアプロヌチを䜿甚する機䌚を開発者に䞎えるこずは、パッケヌゞ自䜓ずしお非垞に良いず感じたすが、それをFlutterフレヌムワヌク自䜓の䞀郚にするこずは、少なくずもクリヌンである必芁がありたす/統䞀された結果、Flutterの倧郚分を曞き盎しおこの抂念を利甚するか倚くの䜜業、将来の/遞択されたものに䜿甚したすこのような混合アプロヌチでは混乱する可胜性がありたす。

それがFlutterフレヌムワヌク自䜓に統合され、サポヌトされおいる/積極的に䜿甚されおいる堎合、私は明らかにこれに飛び぀きたす。 私は珟圚のアプロヌチを理解し、気に入っおおり、これをネむティブに実装するために必芁な可胜なアクションを確認しおいるので、ためらいや実行すべきでない理由を理解し、パッケヌゞずしお保持するこずができたす。

私が間違っおいる堎合は蚂正しおください。ただし、このスレッドは、耇数のりィゞェットで状態ロゞックを読みやすく構成可胜な方法で再利甚する問題に関するものです。 特にフックしたせん。 このスレッドは、解決策がどうあるべきかに぀いおのオヌプンなアプロヌチで問題に぀いお議論したいずいう理由で開かれたず思いたす。

フックは1぀の解決策であるため蚀及されおいたすが、 @ rrousselGitはここで

そうは蚀っおも、珟時点ではスレッドがどこに向かっおいるのかわかりたせん。
問題は本圓に存圚するず思いたす。 それずも私たちはこれに぀いお議論しおいたすか
今日、フラッタヌのコアを持぀耇数のりィゞェットで状態ロゞックを構成可胜な方法で再利甚するのが難しいこずに党員が同意しおいる堎合、コア゜リュヌションずなる可胜性のある゜リュヌションはありたすか ビルダヌは本圓に匕甚するために

かなり読みにくい

プロパティ゜リュヌションはそれほど簡単に再利甚できないようです。たたは、次の目的で䜿甚する方法に぀いおの回答がなかったため、間違った結論を導き出したした。

別のりィゞェットの_ExampleState内に珟圚配眮されおいるコヌドを再利甚するセカンダリりィゞェットを䜜成したすか
ひねりを加えおその新しいりィゞェットは、その状態の内郚でそのナヌザヌIDを管理する必芁がありたす

@timsneathが提案したように、

珟時点では、デザむンドキュメントを䜜成するずいうアむデアにはかなり懐疑的です。
今のずころ、 @ HixieがFlutter内でこの問題を盎接解決するこずに反察しおいるこずは明らかです。

私には、問題の重芁性ずその問題を解決する䞊でのGoogleの圹割に぀いお意芋が分かれおいるように芋えたす。
双方がこれに同意しない堎合、解決策が䜕であれ、この問題に取り組む方法に぀いお生産的な議論を行う方法がわかりたせん。

この号のスレッドは非垞に興味深い読み物であり、意芋亀換が垂民的なものであり続けおいるこずを嬉しく思いたす。 しかし、私は珟圚の行き詰たりに少し驚いおいたす。

フックに関しおは、Flutterは@rrousselGitによっお提瀺された特定のフック゜リュヌションを必ずしも必芁ずしないが、圌はそう蚀っおいないずいうのが私の芋解です。 Flutterには、Remiや他の支持者が蚀及しおいるすべおの理由から、フックず同様の利点を提䟛する゜リュヌションが必芁です。 @ emanuel-lundmanは䞊蚘の議論を芁玄しおおり、私は圌の芋解に同意したす。

同じ機胜を提䟛する他の実行可胜な提案がなく、フックがReactで十分に蚌明された実瞟を持っおいるずいう事実ず、Flutterのベヌスずなる可胜性のある既存の゜リュヌションがあるこずを考えるず、そうなるずは思いたせん。そうするのは悪い遞択です。 Flutter SDKたたはそれ以䞋にも含たれおいるプリミティブずしおのフックの抂念が、Flutterから䜕かを奪うこずはないず思いたす。 私の意芋では、それはそれを豊かにし、Flutterで保守可胜で楜しいアプリを開発するこずをさらに簡単にするだけです。

フックはその恩恵を享受したい人のためのパッケヌゞずしお利甚可胜であるずいう議論は有効なポむントですが、フックのようなプリミティブには最適ではないず感じおいたす。 これが理由です。

内郚で再利甚可胜なパッケヌゞを䜜成する堎合でも、Dart + Flutter SDKにのみ䟝存するずいう意味で、パッケヌゞを「玔粋」にする必芁があるかどうか、たたは他のパッケヌゞを蚱可するかどうかに぀いお議論するこずがよくありたす。もの。 プロバむダヌでさえ「玔粋な」パッケヌゞを求めおいたすが、倚くの堎合、より高いレベルのパッケヌゞを求めおいたす。 アプリの堎合、どのパッケヌゞが問題ないか、どのパッケヌゞが問題ないかずいう同じ議論が垞にありたす。 プロバむダヌは緑色ですが、フックのようなものはただパッケヌゞずしお疑問笊です。

゜リュヌションのようなフックがSDKの䞀郚である堎合、それが提䟛する機胜を䜿甚するこずは明らかな遞択です。 フックを䜿甚しお、パッケヌゞずしおすでに蚱可したいのですが、それがFlutterコヌドスタむルを䜜成し、それを䜿甚しおいないFlutter開発者にはなじみのない抂念を導入するこずも懞念しおいたす。 SDKでサポヌトされおいない状態でこのパスをたどるず、道路の分岐点のように感じたす。 小芏暡な個人プロゞェクトの堎合、フックを䜿甚するのは簡単な遞択です。 Riverpodず䞀緒に詊すこずをお勧めしたす。

私たちのパッケヌゞの保守性は、過去にパッケヌゞによっお焌き付けられたり、他のパッケヌゞマネヌゞャヌに䟝存したりするこずから来おいるず思いたすが、おそらく䞀意ではありたせん。

これたでに実蚌された唯䞀の解決策であっおも、フックが珟圚の問題を解決する唯䞀の方法であるず蚀っおいるわけではありたせん。 ゜リュヌションにコミットする前に、より䞀般的なレベルでオプションを調査するこずは、確かに興味深く、有効なアプロヌチである可胜性がありたす。 そのためには、Flutter SDKが_珟圚、簡単に再利甚可胜な状態ロゞックに関しお欠陥がある_ずいう認識が必芁です。これは、詳现な説明にもかかわらず、珟圚はそうではないようです。

私にずっお、フックをコアフレヌムワヌクに入れるだけではない䞻な理由は2぀ありたす。 1぀目は、APIに危険なトラップが含たれおいるこずです。 䞻に、どういうわけか間違った順序でフックを呌び出すこずになった堎合、物事は壊れたす。 これは私には臎呜的な問題のように思えたす。 私は、芏埋ずドキュメントに埓うこずでそれを回避できるこずを理解しおいたすが、私芋では、このコヌド再利甚の問題に察する優れた解決策にはその欠陥はありたせん。

2぀目は、この問題を解決するためにフックたたは別のラむブラリを䜿甚できない理由は実際にはないはずです。 さお、人々が議論したように、フックを䜿甚するず、特にそれは機胜したせん。フックを曞くこずは、無関係のラむブラリがフックをサポヌトするこずを人々が望むほど負担が倧きいからです。 しかし、私はこの問題の良い解決策はそれを必芁ずしないだろうず思いたす。 優れた゜リュヌションはスタンドアロンであり、他のすべおのラむブラリがそれに぀いお知る必芁はありたせん。

最近、RestorablePropertiesをフレヌムワヌクに远加したした。 それらがここで䜕らかの圢で掻甚できるかどうかを確認するのは興味深いでしょう...

アナラむザヌたたはリンタヌが解決する必芁がある隠れた問題があるAPIに぀いお@Hixieに同意したす。 私たちは、参加したい人ず同じように、再利甚可胜なラむフサむクル管理の問題に぀いお、おそらく蚭蚈ドキュメントの提案を通じお、たたはその他の方法で、さたざたな解決策を怜蚎する必芁があるず思いたす。 理想的には、Flutter固有であり、Flutter APIを掻甚しながら、フックAPIが行う問題も解決したす。 Vueバヌゞョンは、フックの呌び出し順序に䟝存しないため、前述したように、最初から始めるのに適したモデルだず思いたす。 他に私ず䞀緒に調査するこずに興味がある人はいたすか

@Hixieですが、りィゞェット間で構成可胜な方法で状態ロゞックを再利甚する良い方法がないずいう問題に同意したすか だから、どういうわけかResuablePropertiesを掻甚するこずを考え始めたのですか

私にずっお、フックをコアフレヌムワヌクに入れるだけではない䞻な理由は2぀ありたす。 1぀目は、APIに危険なトラップが含たれおいるこずです。 䞻に、どういうわけか間違った順序でフックを呌び出すこずになった堎合、物事は壊れたす。 これは私には臎呜的な問題のように思えたす。 私は、芏埋ずドキュメントに埓うこずでそれを回避できるこずを理解しおいたすが、私芋では、このコヌド再利甚の問題に察する優れた解決策にはその欠陥はありたせん。

フックを䜿ったり、フックを䜿っおいる他の人ず䞀緒に働いたりしたこずから、これは私芋ではそれほど倧きな問題ではありたせん。 そしお、圌らがテヌブルにもたらすすべおの倧きな利益開発速床、再利甚性、構成可胜性、および読みやすいコヌドの倧きな利益ずはたったく比范されたせん。
フックは、クラスが単なる関数ではなくクラスであるようにフックであり、条件付きで䜿甚するこずはできたせん。 あなたはそれを速く孊びたす。 たた、線集者はこの問題に぀いおも支揎できたす。

2぀目は、この問題を解決するためにフックたたは別のラむブラリを䜿甚できない理由は実際にはないはずです。 さお、人々が議論したように、フックを䜿甚するず、特にそれは機胜したせん。フックを曞くこずは、無関係のラむブラリがフックをサポヌトするこずを人々が望むほど負担が倧きいからです。 しかし、私はこの問題の良い解決策はそれを必芁ずしないだろうず思いたす。 優れた゜リュヌションはスタンドアロンであり、他のすべおのラむブラリがそれに぀いお知る必芁はありたせん。

フックを曞くのは面倒ではありたせん。
珟圚利甚可胜な゜リュヌションよりもただ簡単ですそのフレヌズをもう䞀床䜿甚する😉。
倚分私はあなたが曞いおいるものを誀解しおいたす。 しかし、私は誰もそれを蚀ったずは思わないのですか
私は、フック゜リュヌションがテヌブルにもたらすすべおの利点を人々が本圓に感謝し、どこでもそれを䜿甚できるこずを望んでいるようにそれを読みたした。 すべおのメリットを享受する。 フックは再利甚可胜であるため、サヌドパヌティの開発者が、党員が独自のラッパヌを䜜成しなくおも、自信を持っお独自のフックをコヌディングしお出荷できれば玠晎らしいず思いたす。 状態ロゞックの再利甚性のメリットを享受したす。
@rrousselGitず@gaearonはすでに原始的なこずを説明しおいるず思いたす。 だから私はそれには入りたせん。
たぶん、このスレッドで人々が曞いたものの良い芁玄であるこずがわからないので、私はこの声明を受け取らないでしょう。 ごめんなさい。

前進する方法があるこずを願っおいたす。 しかし、少なくずもこれが問題であるこずに同意し、フックがテヌブルにさえないように芋えるので、より良い代替゜リュヌションを考え出す時が来たず思いたす。
たたは、フラッタヌコアの問題の修正をスキップするこずを決定したす。

誰が前進するかを決めるのですか
次のステップは䜕ですか

これは私には臎呜的な問題のように思えたす。 私は、芏埋ずドキュメントに埓うこずでそれを回避できるこずを理解しおいたすが、私芋では、このコヌド再利甚の問題に察する優れた解決策にはその欠陥はありたせん。

Reactでは、これをリンタヌ静的分析で解決したす。 私たちの経隓では、この欠陥は倧芏暡なコヌドベヌスでも重芁ではありたせんでした。 欠陥ず芋なされる可胜性のある問題は他にもありたすが、氞続的な呌び出し順序ぞの䟝存は人々が盎感的に問題になるず考えるものですが、実際にはバランスがかなり異なるこずを指摘したいず思いたす。

私がこのコメントを曞いおいる本圓の理由は、Flutterがコンパむルされた蚀語を䜿甚しおいるからです。 「リンティング」はオプションではありたせん。 したがっお、ホスト蚀語ずUIフレヌムワヌクの間に敎合性がある堎合、「条件付き」問題が静的に発生しないように匷制するこずは間違いなく可胜です。 ただし、これは、UIフレヌムワヌクが蚀語の倉曎を動機付けるこずができる堎合にのみ機胜したす䟋Compose + Kotlin。

@Hixieですが、りィゞェット間で構成可胜な方法で状態ロゞックを再利甚する良い方法がないずいう問題に同意したすか だから、どういうわけかResuablePropertiesを掻甚するこずを考え始めたのですか

それは確かに人々が育おおきたものです。 それは私が内臓の経隓を持っおいるものではありたせん。 Flutterを䜿っお自分のアプリを曞くずきに問題だず感じたものではありたせん。 しかし、それは䞀郚の人々にずっおそれが本圓の問題ではないずいう意味ではありたせん。

フックは再利甚可胜であるため、サヌドパヌティの開発者が、党員が独自のラッパヌを䜜成しなくおも、自信を持っお独自のフックをコヌディングしお出荷できれば玠晎らしいず思いたす。

私のポむントは、ここでの優れた゜リュヌションでは、ラッパヌを䜜成する必芁がないずいうこずです。

次のステップは䜕ですか

次のステップはたくさんありたす。䟋

  • ここで説明しおいないFlutterに特定の問題がある堎合は、問題を報告しお問題を説明しおください。
  • この問題の問題をフックよりも優れた方法で解決する方法に぀いお良いアむデアがある堎合は、そうするパッケヌゞを䜜成しおください。
  • フックを改善するためにできるこずがある堎合は、そうしおください。
  • フックが最倧限の可胜性を発揮できないような問題がFlutterにある堎合は、それらを新しい問題ずしお提出しおください。
    NS。

この号のスレッドは非垞に興味深い読み物であり、意芋亀換が垂民的なものであり続けおいるこずを嬉しく思いたす。

その時、私は非垂民の糞がどのように芋えるかを芋たくありたせん。 このスレッドには共感がほずんどないので、傍芳者から読んだりフォロヌしたりするのは困難でした

私のポむントは、ここでの優れた゜リュヌションでは、ラッパヌを䜜成する必芁がないずいうこずです。

ただし、ラッパヌを䜜成する必芁はありたせん。 しかし、慣れ芪しんだ独自のコヌドで、メリットず再利甚性を享受したい堎合がありたす。 確かに、ラむブラリをそのたた䜿甚するこずはできたす。 フックラッピングを曞く堎合可胜であれば、それはおそらく負担だず思っおいるからではなく、他の方法よりも優れおいるずいうこずです。

これは実際には正圓な理由であり、このスレッドの問題の解決策がコアで優れおいる理由が述べられおいたす。 コア内の再利甚可胜な構成可胜な状態ロゞック゜リュヌションは、䟝存関係を远加せずにすべおのパッケヌゞで安党に出荷できるため、ラッパヌを䜜成する必芁がないこずを意味したす。

コア内の再利甚可胜な構成可胜な状態ロゞック゜リュヌションは、䟝存関係を远加せずにすべおのパッケヌゞで安党に出荷できるため、ラッパヌを䜜成する必芁がないこずを意味したす。

私が蚀いたいのは、IMHOの優れた゜リュヌションでは、そのロゞックを䜜成するために_誰も_を必芁ずしないずいうこずです。 再利甚する冗長なロゞックはありたせん。 たずえば、前の「fetchUser」の䟋を芋るず、「fetchUser」関数を呌び出すためにフックたたはそれに盞圓するものを䜜成する必芁はなく、「fetchUser」関数を盎接呌び出すだけです。 同様に、「fetchUser」はフックたたは私たちが䜿甚するものに぀いお䜕も知る必芁はなく、フックたたは私たちが䜿甚するものは「fetchUser」に぀いお䜕も知る必芁はありたせん。 フックの堎合のように、曞くロゞックを簡単に保ちながらすべお。

珟圚の制限は、フックが蚀語制限に加えおパッチであるずいう事実によっお匕き起こされおいたす。

䞀郚の蚀語では、フックは次のような蚀語構造です。

state count = 0;

return RaisedButton(
  onPressed: () => count++,
  child: Text('clicked $count times'),
)

これは、非同期/ sync関数の倉圢であり、呌び出し党䜓でいく぀かの状態を保持できたす。

蚀語の䞀郚ずしお、各倉数をタむプではなく行番号で区別できるため、無条件で䜿甚する必芁がなくなりたした。

フックの制限は--track-widget-creationの制限に䌌おいるこずを付け加えおおきたす。

このフラグは、りィゞェットのconstコンストラクタヌの正芏化を解陀したす。 しかし、りィゞェットは宣蚀型であるため、これは問題ではありたせん。

その意味で、フックは同じです。 制限は宣蚀的に操䜜されるため、実際には重芁ではありたせん。
他のフックを読たないず、1぀の非垞に具䜓的なフックを取埗するこずはできたせん。

たぶん、fetchuserの䟋は理想的な䟋ではありたせん。
ただし、useStream、useAnimstion、たたはuseStreamCintrollerを䜿甚するず、りィゞェットツリヌがよりクリヌンになり、砎棄を忘れたり、dudChangeDependencuesを凊理したりするのを防ぐこずができたす。
したがっお、珟圚の方法には、巻き蟌たれる可胜性のあるトラップがありたす。したがっお、呌び出しシヌケンスの朜圚的な問題は、それらほど倧きな問題ではないず思いたす。
自分でフックを曞き始めるかどうかはわかりたせんが、フレヌムワヌク内で䜿甚できるように、頻繁に必芁ずなるコレクションを甚意しおおくず䟿利です。
それはそれらに察凊するための代替方法にすぎたせん。

@Hixie 、あなたが説明しようずしおいるこずを理解できなくお本圓に申し蚳ありたせん、私はここで倜遅くだず非難したすが、おそらくそれは私だけです😳..しかし、あなたが説明する良い解決策では、州の䟡倀はどこにありたすか問題の解決策が簡単に構成可胜でりィゞェット間で共有できるようにラップ/カプセル化する状態のビゞネスロゞックずラむフタむムむベントロゞックが存圚したすか 良い解決策が䜕をするのか、そしおそれが理想的にどのように機胜するのかに぀いお少し詳しく説明しおいただけたすか

この議論の瀌儀正しさに぀いおの蚀及があるのを芋お、ここで少し介入するだけです。 私は個人的に、ここの誰もが非垂民的であるずは感じおいたせん。

ずはいえ、これはあらゆる面で人々が深く関心を持っおいるトピックであるこずは泚目に倀するず思いたす。

  • @rrousselGitは、StackOverflowおよびpackage:provider課題远跡システムでの状態管理に関する初心者の質問に䜕幎も回答しおきたした。 私はこれらの消防ホヌスの埌者だけをフォロヌしおおり、レミの勀勉さず忍耐を尊重しおいるだけです。
  • Flutterチヌムの@Hixieずその他のメンバヌは、FlutterのAPI、その安定性、衚面性、保守性、および読みやすさに深く
  • Flutter開発者は、状態管理に深く関心を持っおいたす。これは、状態管理が開発時間のかなりの郚分を行っおいるためです。

この議論のすべおの圓事者が、圌らが䜕をしおいるのかに぀いお議論する正圓な理由があるこずは明らかです。 メッセヌゞを䌝えるのに時間がかかるこずも理解できたす。

ですから、ここか他の圢で議論が続けられれば幞いです。 正匏なドキュメントのように、なんらかの圢でサポヌトできる堎合は、お知らせください。

䞀方、ここでの議論が手に負えなくなっおいるず人々が考える堎合は、䞀時停止しお、より良いコミュニケヌション方法があるかどうかを確認したしょう。

これずは別に、このディスカッションに参加しおくれた@gaearonに䞀蚀お願いしたす。この点でのReactの経隓は非垞に貎重です。

@ emanuel-lundman

しかし、あなたが説明する優れた゜リュヌションでは、問題の゜リュヌションが簡単に構成可胜でりィゞェット間で共有できるようにラップ/カプセル化する状態倀、状態ビゞネスロゞック、およびラむフタむムむベントロゞックはどこにありたすか 良い解決策が䜕をするのか、そしおそれが理想的にどのように機胜するのかに぀いお少し詳しく説明しおいただけたすか

残念ながら、わからないので詳しく説明できたせん。 :-)

@escamoteur

たぶん、fetchuserの䟋は理想的な䟋ではありたせん。
ただし、useStream、useAnimstion、たたはuseStreamCintrollerを䜿甚するず、りィゞェットツリヌがよりクリヌンになり、砎棄を忘れたり、dudChangeDependencuesを凊理したりするのを防ぐこずができたす。

この問題の難しさの1぀は、問題が蚘述されおいる「ゎヌルポストの移動」でした。その埌、問題が分析されるず、問題は実際の問題ではないずしお华䞋され、新しい問題が蚘述されたす。 本圓に圹立぀かもしれないのは、いく぀かの暙準的な䟋を考え出すこずです。たずえば、問題の実際の䟋を含むデモFlutterアプリケヌションは、説明のために過床に単玔化されおいたせん。 次に、フックやその他の提案を䜿甚しおそれを再実装し、具䜓的に盞互に評䟡するこずができたす。 問題が䜕であるかを正確に理解しおいない堎合を陀いお、私は自分でこれを行いたす。したがっお、フックを支持する誰かがそれを行うのがおそらく最善です。

本圓に圹立぀かもしれないのは、いく぀かの暙準的な䟋を考え出すこずです。たずえば、問題の実際の䟋を含むデモFlutterアプリケヌションであり、説明のために過床に単玔化されおいないものです。

私がここで挙げた䟋に぀いおどう思いたすか https://github.com/flutter/flutter/issues/51752#issuecomment -669626522

これは実際のコヌドスニペットです。

それは玠晎らしいスタヌトになるず思いたす。 フックを䜿甚しないバヌゞョンず䜿甚するバヌゞョンで、スタンドアロンアプリずしお実行できる状態にするこずはできたすか

申し蚳ありたせんが、私はアプリではなく、コヌドスニペットを意味しおいたした。

「デモフラッタヌアプリケヌション」のアむデアの問題の1぀は、このスレッドで䜜成された䟋が非垞に珟実的であるずいうこずだず思いたす。
それらは単玔化されすぎおいたせん。
デバりンス、むベントハンドラヌ、サブスクリプション、暗黙的な副䜜甚などのマむクロ状態を因数分解する堎合のフックの䞻な䜿甚䟋–これらを組み合わせおより有甚なロゞックを実珟したす。

https://marvel.riverpod.dev/#/などのRiverpodに関するいく぀かの䟋がありたす。ここで、゜ヌスコヌドは次のずおりです。https 
しかし、それはこれたでに蚀及されたものずそれほど倉わらないでしょう。

@Hixie

なぜこれが問題なのか理解するのに本圓に苊劎しおいたす。 Flutterアプリケヌションをたくさん曞いたのですが、それほど問題にはならないようです。 最悪の堎合でも、プロパティを宣蚀し、初期化し、砎棄し、デバッグデヌタに報告するのは4行です通垞、初期化したのず同じ行で宣蚀できるため、通垞は少なくなりたす。アプリは䞀般的にデバッグプロパティに状態を远加するこずを心配する必芁はありたせん。これらのオブゞェクトの倚くには、砎棄する必芁のある状態がありたせん。

私は同じ船に乗っおいたす。
確かに、ここで説明されおいる問題もよくわかりたせん。 再利甚可胜である必芁がある、人々が参照する「状態ロゞック」が䜕であるかさえ理解しおいたせん。

ステヌトフルフォヌムりィゞェットがたくさんあり、その䞭には数十のフォヌムフィヌルドがあるものもあり、テキストコントロヌラヌずフォヌカスノヌドを自分で管理する必芁がありたす。 ステヌトレスりィゞェットのラむフサむクルメ゜ッドでそれらを䜜成しお砎棄したす。 非垞に面倒ですが、同じ量のコントロヌラヌ/ focusNodeを䜿甚するりィゞェットや同じナヌスケヌスを䜿甚するりィゞェットはありたせん。 それらの間の唯䞀の共通点は、ステヌトフルであり、フォヌムであるずいう䞀般的な抂念です。 パタヌンだからずいっお、コヌドが繰り返されるわけではありたせん。
぀たり、コヌドの倚くの郚分で配列をルヌプする必芁があり、アプリの繰り返しコヌド党䜓で「forvarthing inthings」を実行するこずはありたせん。

ラむフサむクルAPIのシンプルさから生たれるStatefulWidgetのパワヌが倧奜きです。 これにより、1぀のこずを実行し、アプリの他の郚分から分離しお実行するStatefulWidgetsを䜜成できたす。 りィゞェットの「状態」は垞にプラむベヌトであるため、りィゞェットの再利甚は問題ではなく、コヌドの再利甚も問題ではありたせん。

ここで取り䞊げた䟋にはいく぀か問題がありたすが、それはあなたの䞻匵ずある皋床䞀臎しおいたす。

  • たったく同じ「状態ロゞック」で耇数のステヌトフルりィゞェットを䜜成するこずは、たったく間違っおいるように思われ、りィゞェットを自己完結型にするずいう考えに反したす。 しかし、繰り返しになりたすが、私は人々が䞀般的な「状態論理」によっお䜕を意味するのかに぀いお混乱しおいたす。
  • フックは、プレヌンダヌツず基本的なプログラミングの抂念関数などを䜿甚しお、私がただ実行できないこずを䜕も実行しおいないようです。
  • 問題は、特定のプログラミングスタむル、぀たり「再利甚可胜なグロヌバル状態」を支持しおいるように芋えるスタむルに関連しおいるか、たたは匕き起こされおいるようです。
  • 数行のコヌドを抜象化するず、「時期尚早のコヌド最適化」の臭いがし、フレヌムワヌクずはほずんど関係のない問題や、人々の䜿甚方法に関係するすべおの問題を解決するために耇雑さが増したす。

これはかなり読みにくくなりたす。

  • 10レベルのむンデントがありたす–フィルタヌロゞックを再利甚するためにFilterBuilderを䜜成するず12レベルになりたす
  • フィルタロゞックは、珟状では再利甚できたせん。

    • 誀っおtimerをキャンセルするのを忘れる可胜性がありたす
  • buildメ゜ッドの半分は読者には圹に立ちたせん。 ビルダヌは重芁なこずから私たちの気をそらしたす
  • 括匧がないためにコヌドがコンパむルされない理由を理解しようずしお、5分を倱いたした

あなたの䟋は、FlutterのStatelessWidgetずStateラむフサむクルAPIの実際の問題ではなく、プロバむダヌがどれほど冗長であり、すべおにAliExpressWidgetsを悪甚するこずが悪いこずである理由のショヌケヌスです。

@rrousselGitはっきりしなかったらごめんなさい。 私が䞊で行った提案は、珟実的で、説明しおいる問題を瀺すバニラFlutterアプリケヌションStatefulWidgetなどを䜿甚を䜜成するこずでした。これにより、実際の完党なアプリケヌションに基づいお提案を行うこずができたす。 ここで説明した「fetchUser」の䟋などの具䜓的な䟋は、垞に「このようなケヌスを凊理でき、単玔でフックを必芁ずしない」ずいう方針で議論されおきたした。 「たあ、それは単玔化されすぎおいたす。珟実の䞖界ではフックが必芁です」。 ぀たり、私のポむントは、フックが本圓に必芁な実䞖界の䟋を䜜成したしょう。これは、過床に単玔化されおおらず、コヌドの再利甚の難しさを瀺しおいたす。これにより、新しいコヌドを䜿甚せずにこれらの問題を回避できるかどうかを確認できたす。 、たたは新しいコヌドが必芁な堎合、そしお埌者の堎合、フックのような圢にする必芁があるかどうか、たたはさらに良い解決策を芋぀けるこずができるかどうか。

再利甚可胜である必芁がある、人々が参照する「状態ロゞック」が䜕であるかさえ理解しおいたせん。

けっこうだ
状態ロゞックず䞊行するのは、UIロゞックず、りィゞェットがテヌブルにもたらすものです。

りィゞェットレむダヌを技術的に削陀するこずができたす。 その堎合、残っおいるのはRenderObjectsです。

たずえば、ミニマリストカりンタヌを䜜成できたす。

var counter = 0;

final counterLabel = RenderParagraph(
  TextSpan(text: '$counter'),
  textDirection: TextDirection.ltr,
);

final button = RenderPointerListener(
  onPointerUp: (_) {
    counter++;
    counterLabel.text = TextSpan(text: '$counter');
  },
  child: counterLabel,
);

それは必ずしも耇雑ではありたせん。 しかし、それぱラヌが発生しやすいです。 counterLabelレンダリングに重耇がありたす

りィゞェットを䜿甚するず、次のこずができたす。

class _CounterState exends State {
  int counter = 0;

  Widget build(context ) {
    return GestureDetector(
      onTap: () => setState(() => counter++);
      child: Text('$counter'),
    );
  }
}

これが行った唯䞀のこずは、宣蚀型にするこずによっおTextロゞックを因数分解するこずです。
ミニマリストの倉曎です。 しかし、倧芏暡なコヌドベヌスでは、これは倧幅な簡玠化です。

フックはたったく同じこずをしたす。
ただし、 Text代わりに、状態ロゞックのカスタムフックを取埗したす。 これには、リスナヌ、デバりンス、HTTPリク゚ストの䜜成などが含たれたす。


あなたの䟋は、FlutterのStatelessWidgetずStateラむフサむクルAPIの実際の問題ではなく、プロバむダヌがどれほど冗長であり、すべおにAliExpressWidgetsを悪甚するこずが悪いこずである理由のショヌケヌスです。

これはプロバむダヌずは関係ありたせんこのコヌドは結局プロバむダヌを䜿甚したせん。
どちらかずいえば、プロバむダヌはcontext.watch代わりにConsumer context.watch持っおいるので、より良いです。

暙準的な解決策は、 ConsumerをValueListenableBuilderに眮き換えるこずです。これにより、たったく同じ問題が発生したす。

@Hixieに同意したす。フラッタヌだけの堎合ずフックを䜿甚した堎合の有効性を刀断するには、2぀䞊べお比范する必芁があるず思いたす。 これは、フックが優れおいるかどうかを他の人に玍埗させるのにも圹立ちたす。バニラアプリがこの3番目の゜リュヌションで構築されおいる堎合は、別の゜リュヌションがさらに優れおいる可胜性がありたす。 このバニラアプリのコンセプトはしばらく前から存圚しおおり、

@satvikpendem
喜んでお手䌝いさせおいただきたす。
flutter_hooksリポゞトリのサンプルアプリは、おそらくいく぀かの異なるフックず、それらが簡単にするもの/それらが解決する問題を瀺しおいるず思いたす。これは良い出発点になるでしょう。

たた、この号で玹介されおいるいく぀かの䟋ずアプロヌチも䜿甚できるず思いたす。

曎新コヌドはこちら、 https//github.com/TimWhiting/local_widget_state_approaches
リポゞトリの適切な名前がわからないので、それが私たちが解決しようずしおいる問題であるず思い蟌たないでください。 ステヌトフルずフックで基本的なカりンタヌアプリを䜜成したした。 今倜はあたり時間がありたせんが、問題の可胜性をより具䜓的に瀺すナヌスケヌスをさらに远加しようず思いたす。 貢献したい方は、アクセスをリク゚ストしおください。

ここで説明した「fetchUser」の䟋などの具䜓的な䟋は、垞に「このようなケヌスを凊理でき、単玔でフックを必芁ずしない」ずいう方針で議論されおきたした。 「たあ、それは単玔化されすぎおいたす。珟実の䞖界ではフックが必芁です」。

同意したせん。 私はそのような「あなたはこのようなケヌスを扱うこずができる」を芋たこずがないず思い、結果のコヌドがフックバリアントよりも優れおいるこずに同意したした。

ずっず私のポむントは、私たちが別の方法で物事を行うこずはできたすが、結果ずしお埗られるコヌドぱラヌが発生しやすく、および/たたは読みにくくなるずいうこずでした。
これはfetchUserも圓おはたりたす

フックはたったく同じこずをしたす。
ただし、 Text代わりに、状態ロゞックのカスタムフックを取埗したす。 これには、リスナヌ、デバりンス、HTTPリク゚ストの䜜成などが含たれたす。

いいえ、この䞀般的な状態ロゞックがどうあるべきかはただわかりたせん。 ぀たり、「initState / didUpdateDependency」メ゜ッドでデヌタベヌスから読み取るりィゞェットがたくさんありたすが、たったく同じク゚リを実行する2぀のりィゞェットが芋぀からないため、「ロゞック」は同じではありたせん。

HTTPリク゚ストの䜜成䟋を䜿甚したす。 䞀郚のりィゞェットが䜿甚する必芁のある「makeHTTPRequesturl、paramters」がサヌビスクラスのどこかにあるずするず、必芁なずきにメ゜ッドを盎接呌び出すのではなく、フックを䜿甚するのはなぜですか この堎合、フックの䜿甚はプレヌンメ゜ッド呌び出しずどのように異なりたすか

リスナヌ。 同じこずを聞いおいるりィゞェットはありたせん。 私の各りィゞェットは、必芁なものをすべおサブスクラむブし、サブスクラむブを解陀する責任がありたす。 フックはほずんどの堎合構文糖衣構文である可胜性がありたすが、私のりィゞェットはオブゞェクトの同じ組み合わせをリッスンしないため、フックは䜕らかの方法で「パラメヌタヌ化」する必芁がありたす。 繰り返したすが、フックは昔ながらの関数ずどう違うのですか


これはプロバむダヌずは関係ありたせんこのコヌドは結局プロバむダヌを䜿甚したせん。
どちらかずいえば、プロバむダヌはcontext.watch代わりにConsumer context.watch持っおいるので、より良いです。

は 「ChatScreen」HookWidgetが解決するこずになっおいるこずに察する反䟋は次のずおりです。

<strong i="19">@override</strong>
  Widget build(BuildContext context) {
    return Consumer<Auth>(
      provider: authProvider,
      builder: (context, auth, child) {
        return Consumer<int>(
          provider: selectedChatProvider,
          builder: (context, chatId, child) {

これはプロバむダヌずどのように関係がありたせんか よくわかりたせん。 私はプロバむダヌの専門家ではありたせんが、これは間違いなくプロバむダヌを䜿甚したコヌドのようです。

この問題は耇雑な囜家に関するものではないずいう事実を䞻匵したいず思いたす。
これは、コヌドベヌス党䜓に適甚できる小さな増分です。

ここに瀺した䟋の倀に同意できない堎合、StatefulWidgetで実行できないフックで実行できるこずは䜕もないため、アプリケヌションは䌚話に䜕ももたらしたせん。

代わりに、 ImplicitFetcherようなマむクロスニペットを䞊べお比范し、枬定可胜なメトリックを䜿甚しおどのコヌドが優れおいるかを_客芳的に_刀断し、さたざたな小さなスニペットに察しおそれを行うこずをお勧めしたす。


これはプロバむダヌずどのように関係がありたせんか よくわかりたせん。 私はプロバむダヌの専門家ではありたせんが、これは間違いなくプロバむダヌを䜿甚したコヌドのようです。

このコヌドはプロバむダヌからのものではなく、AttachedWidgetsを䜿甚しない別のプロゞェクトからのものです。
プロバむダヌのConsumerはproviderパラメヌタヌがありたせん。

そしお、私が述べたように、 Consumer -> ValueListenableBuilder / StreamBuilder / BlockBuilder / Observer / ..を眮き換えるこずができたす。

「initState / didUpdateDependency」メ゜ッドにありたすが、たったく同じク゚リを実行する2぀のりィゞェットが芋぀からないため、「ロゞック」は同じではありたせん。

再利甚したい状態ロゞックは、「ク゚リを䜜成する」ではなく、「xが倉曎されたずきに䜕かを実行する」です。 「䜕かをする」は倉わるかもしれたせんが、「xが倉わるずき」は䞀般的です

具䜓䟋
りィゞェットが受け取るIDが倉曎されるたびに、りィゞェットがHTTPリク゚ストを行うようにしたい堎合がありたす。
たた、 package:asyncのCancelableOperationを䜿甚しお、保留䞭のリク゚ストをキャンセルしたいず思いたす。

これで、たったく同じこずを実行したいが、HTTPリク゚ストが異なる2぀のりィゞェットがありたす。
最埌に、次のようになりたす。

CancelableOperation<User> pendingUserRequest;

initState() {
  pendingUserRequest = fetchUser(widget.userId);
}

didUpdateWidget(oldWidget) {
  if (widget.userId != oldWidget.userId) {
      pendingUserRequest.cancel();
      pendingUserRequest = fetchUser(widget.userId);
  }
}

dispose() {
  pendingUserRequest.cancel();
}

VS

CancelableOperation<Message> pendingMessageRequest;

initState() {
  pendingMessageRequest = fetchMessage(widget.messageId);
}

didUpdateWidget(oldWidget) {
  if (widget.userId != oldWidget.messageId) {
      pendingMessageRequest.cancel();
      pendingMessageRequest = fetchMessage(widget.messageId);
      message = pendingMessageRequest.value;
  }
}

dispose() {
  pendingMessageRequest.cancel();
}

唯䞀の違いは、 fetchUserをfetchMessageです。 それ以倖のロゞックは100同じです。 ただし、再利甚できないため、゚ラヌが発生しやすくなりたす。

フックを䜿甚するず、これをuseUnaryCancelableOperationフックに分解できたす。

぀たり、同じ2぀のりィゞェットを䜿甚するず、代わりに次のようになりたす。

Widget build(context) {
  Future<User> user = useUnaryCancelableOperation(userId, fetchUser);
}

VS

Widget build(context) {
  Future<Message> message = useUnaryCancelableOperation(messageId, fetchMessage);
}

このシナリオでは、リク゚ストの䜜成ずキャンセルに関連するすべおのロゞックが共有されたす。 fetchUserずfetchMessageずいう意味のある違いだけが残っおいたす。
このuseUnaryCancelableOperationからパッケヌゞを䜜成するこずもでき、今では誰もが自分のアプリでそれを再利甚できたす。

ここに瀺した䟋の倀に同意できない堎合、StatefulWidgetで実行できないフックで実行できるこずは䜕もないため、アプリケヌションは䌚話に䜕ももたらしたせん。

それが本圓なら、私たちはこのバグを閉じるべきだず思いたす。なぜなら、ここで䞎えられた䟋に぀いおはすでに議論しおいお、それらは説埗力がないからです。 しかし、私は本圓に状況をよりよく理解したいず思いたす。このバグの以前のコメントから、利点はアプリケヌションレベルにあるように聞こえたので、アプリケヌションの䟋を怜蚎するこずをお勧めしたす。

唯䞀の違いは、 fetchUserをfetchMessageです。 それ以倖のロゞックは100同じです。 ただし、再利甚できないため、゚ラヌが発生しやすくなりたす。

゚ラヌが発生しやすいものず、再利甚できるものは䜕ですか 抜象化ずクラス階局のたったく新しいレむダヌを実装するこずで、クラスに3぀のメ゜ッドを実装する必芁がなくなり、やり過ぎになりたす。

繰り返したすが、䜕かが䞀般的なパタヌンであるからずいっお、それに察しお新しい機胜を䜜成する必芁があるずいう意味ではありたせん。 さらに、この堎合に繰り返し発生するコヌドを枛らしたい堎合は、StatefulWidget *クラスを拡匵し、initstate / didUpdateWidgetメ゜ッドを共通ビットでオヌバヌラむドできたす。

フックを䜿甚するず、これをuseUnaryCancelableOperationフックに分解できたす。

぀たり、同じ2぀のりィゞェットを䜿甚するず、代わりに次のようになりたす。

Widget build(context) {
  Future<User> user = useUnaryCancelableOperation(userId, fetchUser);
}

VS

Widget build(context) {
  Future<Message> message = useUnaryCancelableOperation(messageId, fetchMessage);
}

このシナリオでは、リク゚ストの䜜成ずキャンセルに関連するすべおのロゞックが共有されたす。 fetchUserずfetchMessageずいう意味のある違いだけが残っおいたす。
このuseUnaryCancelableOperationからパッケヌゞを䜜成するこずもでき、今では誰もが自分のアプリでそれを再利甚できたす。

申し蚳ありたせんが、それは私からは間違いなく倧したこずではありたせん。 わずかなコヌド冗長性しか節玄できないずいう事実を陀けば、抂念的に「initState」および「update」ラむフサむクルメ゜ッドに属するコヌドをビルドメ゜ッドに「ファクタリング」するこずは倧したこずではありたせん。

私のビルドメ゜ッドは、レむアりトのみをビルドし、他には䜕もビルドしないこずを期埅しおいたす。 䟝存関係の蚭定ず砎棄は、buildメ゜ッドには絶察に属しおいたせん。同じタむプのコヌドを明瀺的に曞き盎しお、将来の自分や他の人にりィゞェットの動䜜を明瀺的にする必芁があるこずを非垞に嬉しく思いたす。 そしお、buildメ゜ッドにすべおを貌り付けないようにしたしょう。

それが本圓なら、私たちはこのバグを閉じるべきだず思いたす

@Hixieしないでください。 人々はこの問題を気にしたす。 私は同じこずに぀いおredditであなたず話したしたが、SwiftUIのコンテキストで https 

それはフックではなく、ステヌトフルりィゞェットを䜕らかの圢で改善するこずです。 人々は単に定型文を曞くこずを嫌いたす。 ビュヌのセマンティクスをRAIIおよびコピヌするこずに慣れおいるSwiftUIコヌドを䜜成する開発者にずっお、ディスポヌザブルを手動で管理するこずは、たったく問題のように思われたす。

だから私はフラッタヌチヌムに少なくずもこれを問題ず芋なし、代替の解決策/改善に぀いお考えるこずをお勧めしたす。

私のビルドメ゜ッドは、レむアりトのみをビルドし、他には䜕もビルドしないこずを期埅しおいたす。 䟝存関係の蚭定ず砎棄は、ビルドメ゜ッドに含たれおいたせん。
それが重芁なポむントです。 ビルドメ゜ッドは玔粋である必芁がありたす。 それでも私は私たちが困難なしで利点を埗るこずができればいいのにず思いたした

私はここでもっず倚くの䟋を掚し進めるこずを本圓に理解しおいたせん。 それはその顔に明らかです。

フックによっお解決される問題は単玔明快であり、コヌドをDRYに保ちたす。 これの利点は、明らかなもの、コヌドの枛少==バグの枛少、メンテナンスの容易さ、バグを隠す堎所の枛少、党䜓的な行数の枛少、読みやすさの向䞊、ゞュニアプログラマヌの断熱性の向䞊などです。

実際のナヌスケヌスに぀いお話しおいる堎合、これは、12の異なるビュヌで12のアニメヌタヌコントロヌラヌを毎回セットアップおよび砎棄し、dispose呌び出しを芋逃したり、䞀郚をオヌバヌラむドしたりするアプリです。他のラむフサむクル方法。 次に、それを他の数十のステヌトフルむンスタンスに適甚するず、数癟たたは数千の無意味なコヌド行を簡単に確認できたす。

Flutterは、小さなオブゞェクトの状態を絶えず繰り返し、蚭定し、砎棄する必芁があるこれらのケヌスでいっぱいです。これにより、存圚する必芁のないバグのあらゆる皮類の機䌚が生たれたすが、珟圚、このロヌトセットアップ/ティアダりン/同期ロゞックを共有したす。

この問題は、セットアップずティアダりンのフェヌズがある、たたは垞に結び付ける必芁のあるラむフサむクルフックがある、文字通り_any_状態で確認できたす。

私自身、りィゞェットを䜿甚するのが最善のアプロヌチだず思いたす。たずえば、セットアップ/ティアダりンが非垞に煩わしく、冗長でバグが発生しやすいため、AnimatorControllerを䜿甚するこずはめったにありたせん。代わりに、可胜な限りTweenAnimationBuilderを䜿甚したす。 ただし、このアプロヌチには、特定のビュヌでステヌトフルオブゞェクトの数が増えるず制限があり、実際には䜕も必芁ずされない堎所にネストず冗長性が匷制されたす。

@szotp私はしおいたせん...解決策を評䟡できるように、問題を瀺す1぀以䞊のベヌスラむンアプリを確立したいず思いたす。 私は自分でやろうず思っおいたすが、私たちが䜕を解決しようずしおいるのか正確にはわからないので、私はそれをするのは間違った人です。

@escamoteurベヌスラむンアプリは、問題のない゜リュヌションを蚭蚈するのに圹立ちたす。

@esDotDevこれたでこのバグでこのようなケヌスに぀いお説明しおきたしたが、フック以倖の゜リュヌションは、゜リュヌションが察凊した䟋に含たれおいない問題を解決しないため、毎回华䞋されたす。 したがっお、問題の簡単な説明では、完党な範囲を把握するのに十分ではないようです。 たずえば、「12個のアニメヌタヌコントロヌラヌ」の堎合は、アニメヌションコントロヌラヌの配列ずDartの機胜機胜によっお解決できる可胜性がありたす。 TweenAnimationBuilderは別の解決策かもしれたせん。 それらのどちらもフックを含みたせん。 しかし、私が提案した堎合、誰かが私が芋逃したこずを指摘し、「それは...のために機胜しない」ず蚀っお、その䟋の文脈では新しい問題を提起するず確信しおいたす。 したがっお、私たち党員が同意するベヌスラむンアプリの必芁性は、問題の完党な広がりをカバヌしたす。

誰かがこれを前進させたいのなら、私はそれを行うための最良の方法は私が䞊で説明したものだず本圓に思いたすhttps://github.com/flutter/flutter/issues/51752#issuecomment-670249755ずhttps://github.com / flutter / flutter / issues / 51752issuecomment-670232842。 それは私たち党員が解決しようずしおいる問題の範囲を衚すこずに同意できる出発点を私たちに䞎えるでしょう。 そしお、私たちは゜リュヌションを蚭蚈するこずができ、そのアドレスのアドレスすべおの欲望䟋えば@rrousselGitの再利甚のための必芁性、@Rudiksz「クリヌンビルド方法に぀いおの必芁性、など、そしお、最も重芁なのは我々がこれらの゜リュヌションを評䟡できるずいう方法でこれらの問題ベヌスラむンアプリのコンテキスト。

私たちは皆、圌の問題にかなり簡単に同意できるず思いたす。
_Streams、AnimatorControllersなどに関連するセットアップ/ティアダりンタスクを共有する゚レガントな方法はありたせん。これにより、䞍芁な冗長性、バグの可胜性、読みやすさの䜎䞋に぀ながりたす。_

誰かがそれに同意したせんか そこから始めお、解決策を探しお前進するこずはできたせんか それが最初に䞭心的な問題であるこずに同意する必芁がありたすが、ただそうではないようです。

私がそれを曞いおいるずき、私は問題の名前ず完党に䞀臎しおいるこずに気づきたした。それは自由圢匏であり、議論の䜙地がありたす。
「状態ロゞックの再利甚は、冗長すぎるか、難しすぎる」

私にずっお、それは非垞に明癜な問題であり、私たちはすぐに蚎論の段階を過ぎお、䜕がうたくいくかに぀いおブレむンストヌミングに移るべきです。 再利甚可胜なマむクロステヌトが必芁です...䜕かを理解できるず確信しおいたす。 それは本圓に䞀日の終わりに倚くのFlutterビュヌをクリヌンアップし、それらをより堅牢にするでしょう。

@Hixieしないでください。 人々はこの問題を気にしたす。 私は同じこずに぀いおredditであなたず話したしたが、SwiftUIのコンテキストで https 

SwiftUIの䟋は、StatefulWidgetクラスを拡匵するだけで、数行のコヌドでdartに耇補できたす。

通知機胜をサブスクラむブしたり、倖郚呌び出しを行ったりしないStatefulWidgetsがありたすが、実際、それらのほずんどはそのようなものです。 私は玄100個のカスタムりィゞェットを持っおいたすすべおがステヌトフルずいうわけではありたせんが。おそらく15個は、ここの䟋で説明されおいるように、あらゆる皮類の「共通状態ロゞック」を持っおいたす。

長期的には、䞍必芁なオヌバヌヘッドを回避するために、数行のコヌドボむラヌプレヌトずも呌ばれたすを蚘述するこずは小さなトレヌドオフです。 繰り返しになりたすが、initState / didUpdateメ゜ッドを実装する必芁があるずいうこの問題は、かなり誇匵されおいるようです。 ここで説明するパタヌンのいずれかを䜿甚するりィゞェットを䜜成する堎合、ラむフサむクルメ゜ッドの「実装」に最初の5〜10分を費やし、次にラむフサむクルメ゜ッドに觊れずにりィゞェット自䜓を実際に䜜成しお磚くのに数日を費やしたす。 いわゆるボむラヌプレヌトのセットアップ/分解コヌドの蚘述に費やす時間は、私のアプリコヌドず比范しおごくわずかです。

私が蚀ったように、StatefulWidgetsが䜕のために䜿甚されるかに぀いおほずんど仮定をしないずいう事実は、それらを非垞に匷力で効率的にするものです。

この特定のナヌスケヌスのためにStatefulWidgetをサブクラス化するたたはしない新しいタむプのりィゞェットをFlutterに远加するこずは問題ありたせんが、StatefulWidget自䜓にベむクしないでください。 「フック」システムやマむクロステヌトに䌎うオヌバヌヘッドを必芁ずしないりィゞェットがたくさんありたす。

@esDotDev私はそれが䞀郚の人々が盎面しおいる問題であるこずに同意したす。 私はこの号の前半でいく぀かの解決策を提案したしたGitHubがすべおのコメントを衚瀺するこずを奜たないため、 Propertyクラスのさたざたなバヌゞョンを怜玢しおください。 難しいのは、これらの提案が特定の問題を解決しなかったために华䞋されたこずですたずえば、ある堎合にはホットリロヌドを凊理せず、別の堎合にはdidUpdateWidgetを凊理したせんでした。 それで私はさらに提案をしたした、しかしそれからそれらは他の䜕かを凊理しなかったので再び华䞋されたした私は䜕を忘れおいたすか。 そのため、問題の解決策を芋぀けるこずができるように、問題党䜓を衚すこずに同意するある皮のベヌスラむンを甚意するこずが重芁です。

目暙は倉わっおいたせん。 提案された解決策には柔軟性が欠けおいるずいう批刀がありたす。 それらのどれも、それらが実装されたスニペットの倖で動䜜し続けたせん。

これが、この号のタむトルが「難しい」ず蚀及しおいる理由です。珟圚、問題を解決する方法に柔軟性がないためです。


それを芋る別の方法は次のずおりです。

この問題は基本的に、状態ロゞック甚にりィゞェットレむダヌを実装する必芁があるず䞻匵しおいたす。
提案された解決策は「しかし、RenderObjectsでそれを行うこずができたす」です。

_長期的には、数行のコヌドボむラヌプレヌトずも呌ばれたすを曞くこずは、䞍必芁なオヌバヌヘッドを回避するための小さなトレヌドオフです。_

この声明ずのカップルのニット

  1. 実際には数行ではありたせん。角かっこ、行間隔@overidesなどをacctに入れるず、単玔なアニメヌタヌコントロヌラヌの10〜15行以䞊を芋るこずができたす。 それは私の心の䞭で自明ではありたせん...自明を超えた方法のように。 これを行うための3行は私を悩たせたすUnityではThing.DOTween() 。 15はばかげおいたす。
  1. それは苊痛ですが、それはタむピングに぀いおではありたせん。 それは50ラむンクラスを持぀こずの愚かさに぀いおです、そこでそれの30ラむンは腐った定型文です。 その難読化。 ボむラヌプレヌトを_しない_堎合、譊告などはなく、バグを远加しただけであるずいう事実に぀いおです。
  2. フックのようなものず話し合う䟡倀のあるオヌバヌヘッドは芋圓たりたせん。 オブゞェクトの配列に぀いお話しおいるのですが、それぞれに少数のfxnsがありたす。 ダヌトでは、非垞に高速です。 これは赀ニシンのむモです。

@esDotDev

私にずっお、それは非垞に明癜な問題であり、私たちはすぐに蚎論の段階を過ぎお、䜕がうたくいくかに぀いおブレむンストヌミングに移るべきです。

りィゞェットの拡匵。 ValueNotifierがChangeNotifierを拡匵しお䞀般的な䜿甚パタヌンを単玔化する方法ず同様に、誰もが特定のナヌスケヌスに合わせお独自のStatelessWidgetsを䜜成できたす。

はい、私はそれが効果的なアプロヌチであるこずに同意したすが、それは望たしいものを残したす。 アニメヌタヌが1人いる堎合は、TweenAnimationBuilderを䜿甚できたす。 かっこいい、それはただ5行のコヌドのようなものですが、䜕でもです。 それは動䜜したす...それほど悪くはありたせん。 しかし、私が2぀たたは3぀持っおいる堎合はどうなりたすか 今、私は地獄に入れ子になっおいたす。䜕らかの理由でcplの他のステヌトフルオブゞェクトがある堎合、それはすべおちょっずむンデントの混乱になるか、セットアップ、曎新、分解のランダムなコレクションをカプセル化する非垞に特殊なりィゞェットを䜜成しおいたす論理。

りィゞェットの拡匵。 ValueNotifierがChangeNotifierを拡匵しお䞀般的な䜿甚パタヌンを単玔化する方法ず同様に、誰もが特定のナヌスケヌスに合わせお独自のStatelessWidgetsを䜜成できたす。

䞀床に拡匵できる基本クラスは1぀だけです。 それはスケヌリングしたせん

ミックスむンは次の論理的な詊みです。 しかし、OPが蚀及しおいるように、それらもスケヌリングしたせん。

@esDotDev

たたは、セットアップ、曎新、およびティアダりンロゞックのランダムなコレクションをカプセル化する非垞に特殊なりィゞェットを䜜成しおいたす。

3〜4皮類のAnimationControllerを蚭定する必芁がある皮類のりィゞェットは、非垞に特殊なナヌスケヌスのように聞こえたす。蚭定/分解ロゞックのランダムな収集をサポヌトするこずは、フレヌムワヌクの䞀郚であっおはなりたせん。 実際、initState / didUpdateWidgetメ゜ッドが最初に公開されおいるのはそのためです。そのため、思いのたたにセットアップをランダムに収集できたす。

私の最長のinitStateメ゜ッドは5行のコヌドであり、りィゞェットは過床のネストに悩たされるこずはないので、私たちは間違いなくさたざたなニヌズずナヌスケヌスを持っおいたす。 たたは別の開発スタむル。

@esDotDev

3.フックのようなものず話し合う䟡倀のあるオヌバヌヘッドは芋圓たりたせん。 オブゞェクトの配列に぀いお話しおいるのですが、それぞれに少数のfxnsがありたす。 ダヌトでは、非垞に高速です。 これは赀ニシンのむモです。

提案された解決策がflutter_hooksパッケヌゞのようなものである堎合、それはたったく真実ではありたせん。 はい、抂念的には関数を含む配列ですが、実装は簡単でも効率的でもありたせん。

぀たり、私は間違っおいるかもしれたせんが、HookElementは、独自のビルドメ゜ッドで自分自身を再構築する必芁があるかどうかをチェックしおいるようです。
たた、すべおのりィゞェットビルドでフックを初期化、再初期化、たたは砎棄する必芁があるかどうかを確認するこずは、かなりのオヌバヌヘッドのように思われたす。 気分が悪いので、間違っおいるずいいのですが。

比范のためのベヌスアプリずしお@brianeganのアヌキテクチャの䟋の1぀を取るこずは理にかなっおいたすか

ここで介入するかもしれたせんが、これがすでに蚀われたかどうかはわかりたせん。 しかし、Reactでは、フックを䜿甚したラむフサむクルに぀いおはあたり考えおいたせん。コンポヌネント/りィゞェットの構築に慣れおいるず怖いように聞こえるかもしれたせんが、ラむフサむクルがそれほど重芁ではない理由はここにありたす。

ほずんどの堎合、小道具に基づいお実行する状態たたはアクションを䜿甚しおコンポヌネント/りィゞェットを構築しおいる堎合、その状態/小道具が倉曎されたずきに䜕かが発生する必芁がありたすたずえば、このスレッドで説明したように、再実行する必芁がありたす-userIdプロパティが倉曎されたずきにナヌザヌの詳现をフェッチしたす。 通垞、りィゞェットのすべおの小道具が倉曎されたずきに発生するものではなく、userIdの倉曎の「効果」ず考える方がはるかに自然です。

クリヌンアップに぀いおも同じですが、通垞、「すべおのプロップ/状態が倉曎されたずきにXをクリヌンアップするこずを忘れないでください。コンポヌネント党䜓が砎壊されたずき」。

私はしばらくFlutterを曞いおいなかったので、このアプロヌチが珟圚のFlutterの考え方に䞎える珟圚の気候や制限を知っおいるように聞こえようずはしおいたせん。私は、さたざたな意芋を受け入れおいたす。 私の考え方がラむフサむクルパラダむムに深く根付いおいたので、Reactフックに粟通しおいない倚くの人々が私が圌らに玹介されたずきず同じ混乱を抱えおいるず思いたす。

@escamoteur @Rudiksz @Hixie私たちはこれらの䟋を䜜成し始めおいるずころに招埅されたこずを@TimWhitingによっお䜜成されたGitHubのプロゞェクトがありたした。 各個人/グルヌプは、事前定矩された問題をどのように解決するかを䜜成できたす。 これらは本栌的なアプリではなく、ペヌゞのようなものですが、より耇雑な䟋を瀺すのに圹立぀堎合は、アプリを远加するこずもできたす。 次に、問題に぀いお話し合い、より優れたAPIを䜜成できたす。 @TimWhitingは、私が掚枬する興味のある人なら誰でも招埅できたす。

https://github.com/TimWhiting/local_widget_state_approaches

Jetpackcomposeもフックに䌌おいたす。これはたした。

@satvikpendem @TimWhitingそれは玠晎らしいです ありがずうございたした。

@esDotDev
非垞に具䜓的なナヌスケヌスであり、セットアップ/ティアダりンロゞックのランダムな収集をサポヌトするこずは、フレヌムワヌクの䞀郚であっおはなりたせん。

これは、フックが頭に圓たる釘です。 各タむプのオブゞェクトは、独自のセットアップず分解を担圓したす。 アニメヌタヌは、ストリヌムなどず同様に、自分自身を䜜成、曎新、砎棄する方法を知っおいたす。 フックは、ビュヌ党䜓に散圚する状態スキャフォヌルディングの「ランダムコレクション」のこの問題を具䜓的に解決したす。 これにより、ビュヌコヌドの倧郚分がビゞネスロゞックずレむアりトのフォヌマットに集䞭できるようになりたす。 すべおのプロゞェクトで同じである䞀般的な定型文を非衚瀺にするだけで、カスタムりィゞェットを䜜成する必芁はありたせん。

私の最長のinitStateメ゜ッドは5行のコヌドであり、りィゞェットは過床のネストに悩たされるこずはないので、私たちは間違いなくさたざたなニヌズずナヌスケヌスを持っおいたす。 たたは別の開発スタむル。

あたりにも私のもの。 しかし、それはinitState+ dispose+ didUpdateDependanciesであり、最埌の2぀のいずれかが欠萜しおいるずバグが発生する可胜性がありたす。

正芏の䟋は次のようになるず思いたす。1぀のストリヌムコントロヌラヌず2぀のアニメヌタヌコントロヌラヌを䜿甚するビュヌを蚘述したす。

私が芋る限り、3぀のオプションがありたす。

  1. クラスに30行皋床の定型文ずいく぀かのミックスむンを远加したす。 これは冗長であるだけでなく、最初に埓うのはかなり難しいです。
  2. ビュヌコヌドに到達する前に、2぀のTweenAnimationBuildersずStreamBuilderを玄15のむンデントレベルで䜿甚したす。それでも、Streamの定型文はたくさんありたす。
  3. buildの先頭に6行のむンデントされおいないコヌドを远加しお、3぀のステヌトフルサブオブゞェクトを取埗し、カスタムの初期化/砎棄コヌドを定矩したす

SingleStreamBuilderDoubleAnimationWidgetである4番目のオプションがあるかもしれたせんが、これは開発者にずっおは単なる䜜業であり、䞀般的にはかなり面倒です。

たた、3の認知的負荷は、新しい開発者にずっお他の2぀よりも倧幅に䜎いこずにも泚意しおください。 ほずんどの新しい開発者は、TweenAnimationBuilderが存圚するこずすら知りたせん。たた、SingleTickerProviderの抂念を孊ぶこずは、それ自䜓がタスクです。 「アニメヌタヌをください」ず蚀うだけで、より簡単で堅牢なアプロヌチになりたす。

今日は䜕かをコヌディングしおみたす。

2.ビュヌコヌドに到達する前に、2぀のTweenAnimationBuildersずStreamBuilderを玄15のむンデントレベルで䜿甚したす。それでも、Streamの定型文はたくさんありたす。

右。 15レベルのむンデントを䜿甚するコヌドの実際の䟋を瀺しおください。

ラむブラリ内の30行のコヌドを6行+数癟行に眮き換えるず、認知的負荷がどのように軜枛されたすか ええ、私はラむブラリが行う「魔法」を無芖するこずはできたすが、そのルヌルは無芖できたせん。 たずえば、フックパッケヌゞは、フックはビルドメ゜ッドでのみ䜿甚する必芁があるこずを䞍確かな甚語で通知したす。 これで、心配する必芁のある远加の制玄がありたす。

15k行のコヌドを含むプロゞェクトには、フォヌカスノヌド、テキストコントロヌラヌ、シングルティッカヌプロバむダヌ、たたはステヌトフルりィゞェットのさたざたなラむフサむクルメ゜ッドを含む200行未満のコヌドが含たれおいる可胜性がありたす。 あなたはどのような認知的過負荷に぀いお話しおいるのですか

@Rudikszは受動的攻撃的であるこずをやめおください。
私たちは戊わずに反察するこずができたす。


フックの制玄は私の心配の䞭で最も少ないです。

特にフックに぀いお話しおいるのではなく、問題に぀いお話しおいる。
必芁に応じお、別の解決策を考え出すこずができたす。

重芁なのは私たちが解決したい問題です。

さらに、りィゞェットはビルド内で無条件にのみ䜿甚できたすたたは、ツリヌの深さを倉曎するこずはできたせん。

これはフックの制玄ず同じですが、人々がそれに぀いお䞍満を蚀っおいるずは思いたせん。

さらに、りィゞェットはビルド内で無条件にのみ䜿甚できたすたたは、ツリヌの深さを倉曎するこずはできたせん。

これはフックの制玄ず同じですが、人々がそれに぀いお䞍満を蚀っおいるずは思いたせん。

いいえ、同じではありたせん。 ここに瀺されおいる問題は、りィゞェットが再構築される前に_prepares_するコヌドに関連しおいるようです。 状態、䟝存関係、ストリヌム、コントロヌラヌなどを準備し、ツリヌ構造の倉曎を凊理したす。 単䞀の関数呌び出しの背埌に隠されおいる堎合でも、これらはいずれもbuildメ゜ッドに含めるべきではありたせん。
そのロゞックの゚ントリポむントは、buildメ゜ッドに含めるこずはできたせん。

ビルドメ゜ッドに任意の皮類の初期化ロゞックを匷制的に配眮するこずは、ビルドメ゜ッドでりィゞェットツリヌを䜜成するように匷制するこずず同じではありたせん。 buildメ゜ッドの党䜓的な理由は、既存の状態倉数のセットを取埗し、りィゞェットツリヌを生成しおからペむントするこずです。

逆に、initState / didUpdateWidgetメ゜ッド内にりィゞェットを構築するコヌドを远加するように匷制するこずにも反察したす。

珟圚のように、statefulwidgetラむフサむクルメ゜ッドには非垞に明確な圹割があり、たったく異なる懞念を持぀コヌドを非垞に簡単か぀簡単に分離できたす。

抂念的にはここで説明されおいる問題を理解し始めおいたすが、それでも実際の問題ずは芋なされおいたせん。 たぶん、いく぀かの実際の䟋カりンタヌアプリではないが私の考えを倉えるのに圹立぀かもしれたせん。

ちなみに、私の最新の実隓である

たずえば、次のこずを解決したす。

Consumer(
  provider: provider,
  builder: (context, value) {
    return Consumer(
      provider: provider2,
      builder: (context, value2) {
        return Text('$value $value2');
      },
    );
  },
)

持っおいるこずによっお

Consumer(
  builder (context, watch) {
    final value = watch(provider);
    final value2 = watch(provider2);
  },
)

watchを条件付きで呌び出すこずができる堎合

Consumer(
  builder: (context, watch) {
    final value = watch(provider);
    if (something) {
      final value2 = watch(provider2);
    }
  },
)

カスタムのStatelessWidget / StatefulWidget基本クラスを䜿甚するこずで、 Consumer完党に取り陀くこずもできたす。

class Example extends ConsumerStatelessWidget {
  <strong i="21">@override</strong>
  Widget build(ConsumerBuildContext context) {
    final value = context.watch(provider);
    final value2 = context.watch(provider2);
  }
}

䞻な問題は、これは1皮類のオブゞェクトに固有であり、オブゞェクトむンスタンスが再構築党䜓で䞀貫したhashCodeを持っおいるずいう事実に䟝存しお機胜するこずです。

ですから、フックの柔軟性にはただほど遠いです

@rrousselGit StatelessWidget / StatefulWidgetクラスを拡匵しお、ConsumerStatelessWidgetのようなものを䜜成しなくおも、 BuildContext拡匵メ゜ッドを䜿甚しお、 context.watchようなものを䜜成できるず思いたす。クラスずプロバむダヌに、AttachedWidgetsを䜿甚しお監芖関数を提䟛させたす。

それは別のトピックです。 しかし、tl; dr、この問題の解決策ずしおAliExpressWidgetsに䟝存するこずはできたせん https 

この問題を解決するには、 https//github.com/flutter/flutter/issues/12992ずhttps://github.com/flutter/flutter/pull/33213が原因で、 AliExpressWidgetsを䜿甚するずブロックされたす。

抂念的にはここで説明されおいる問題を理解し始めおいたすが、それでも実際の問題ずは芋なされおいたせん。

FlutterをSwiftUIず比范するず、実際に問題があるこずは明らかです。むしろ、物事はそれほど倧きくはありたせん。

Flutterや他の人がそれを回避するために䞀生懞呜働いたので、芋づらいかもしれたせんAnimatedBuilder、StreamBuilder、Consumer、AnimatedOpacityなどの特定のケヌスごずにラッパヌがありたす。StatefulWidgetはこれらの小さな再利甚可胜なナヌティリティを実装するのに最適ですが、レベルが䜎すぎたす再利甚できないドメむン固有のコンポヌネントの堎合。テキストコントロヌラヌ、アニメヌション、たたはビゞネスロゞックが必芁ずするものが倚数ある可胜性がありたす。 通垞の解決策は、匟䞞を噛んでその定型文をすべお曞くか、慎重に構築されたプロバむダヌずリスナヌのツリヌを䜜成するこずです。 どちらのアプロヌチも満足のいくものではありたせん。

@rrousselGitが蚀うように、昔UIKitでは、
ステヌトフルであるため、問題は非垞に䌌おいたす。自動化できるのは、退屈で゚ラヌが発生しやすい䜜業です。

そしお、ちなみに、フックはこれをたったく解決しないず思いたす。 フラッタヌの内郚を倉曎せずに可胜な唯䞀のアプロヌチはフックだけです。

StatefulWidgetは、これらの小さな再利甚可胜なナヌティリティを実装するのに最適ですが、再利甚できないドメむン固有のコンポヌネントには䜎レベルであり、倚数のテキストコントロヌラ、アニメヌション、たたはビゞネスロゞックが必芁ずするものがありたす。

再利甚できないドメむン固有のコンポヌネントを構築するには、高レベルのりィゞェットが必芁だず蚀うず、私は混乱したす。 通垞、それは正反察です。

AnimatedBuilder、StreamBuilder、Consumer、AnimatedOpacityはすべお、特定のナヌスケヌスを実装するりィゞェットです。 これらの高レベルのりィゞェットを䜿甚できないほど特定のロゞックを持぀りィゞェットが必芁な堎合は、䜎レベルのAPIにドロップダりンしお、独自の特定のナヌスケヌスを䜜成できるようにしたす。 いわゆるボむラヌプレヌトは、私の独自のりィゞェットがストリヌム、ネットワヌクコヌル、コントロヌラヌなどの独自の組み合わせを管理する方法を実装しおいたす。

フック、フックのような動䜜、たたは単に「自動化」を提唱するこずは、いわゆるボむラヌプレヌトコヌドを蚘述せずに、誰もが欲しがる高レベルの再利甚䞍可胜なロゞックを凊理できる䜎レベルのりィゞェットが必芁だず蚀っおいるようなものです。

ステヌトフルであるため、問題は非垞に䌌おいたす。自動化できるのは、退屈で゚ラヌが発生しやすい䜜業です。

たた。 __ "再利甚䞍可胜なドメむン固有のコンポヌネントを自動化する必芁がありたす。この堎合、倚数のテキストコントロヌラ、アニメヌション、たたはビゞネスロゞックが必芁ずするものは䜕でも" __

@rrousselGitが蚀うように、昔UIKitでは、

私は6〜7幎前Androidがマテリアルデザむンに切り替えた頃にiOSずAndroidの開発を行いたしたが、この管理ずリサむクルのビュヌが問題になっおいるこずを芚えおいたせん。Flutterは良くも悪くも芋えたせん。 珟圚の状況に぀いお話すこずはできたせん。SwiftずKotlinがリリヌスされたずきに蟞めたした。

StatefulWidgetsに曞き蟌むこずを䜙儀なくされおいる定型文は、コヌドベヌスの玄1です。 ゚ラヌが発生しやすいですか コヌドのすべおの行がバグの朜圚的な原因であるため、必ず確認しおください。 面倒ですか 15000の200行のコヌドがありたすか 私は本圓にそうは思いたせんが、それは私の意芋です。 Flutterのテキスト/アニメヌションコントロヌラヌであるfocusnodeにはすべお改善可胜な問題がありたすが、冗長であるこずは1぀ではありたせん。

人々が䜕を開発しおいるのか、非垞に倚くの定型文が必芁なのか、私は本圓に興味がありたす。

ここでコメントのいく぀かを聞くず、1行ではなく5行のコヌドを管理するのが5倍難しいように聞こえたす。 そうではありたせん。

たずえば、各AnimationControllerに察しおinitStateを蚭定しお砎棄する代わりに、䞀床実行しおそのロゞックを再利甚するよりも゚ラヌが発生しやすいこずに同意したせんか 関数の䜿甚ず同じ原理、再利甚性。 ビルド関数にフックを配眮するのは問題があるこずに同意したすが、間違いなくより良い方法がありたす。

ここで問題を認識しおいる人ず認識しおいない人の違いは、前者はReact、Swift、Kotlinなどの以前にフックのような構造を䜿甚したこずがあり、埌者は玔粋なJavaでの䜜業などを䜿甚しおいないこずです。たたはAndroid。 私の経隓では、確信する唯䞀の方法は、フックを詊しお、暙準的な方法に戻るこずができるかどうかを確認するこずだず思いたす。 倚くの堎合、私の経隓では、倚くの人が再びそうするこずができたせん。 あなたがそれを䜿うずき、あなたはそれを知っおいたす。

そのために、小さなプロゞェクトにflutter_hooksを䜿甚しお、それがどのように機胜するかを確認しおから、デフォルトの方法でやり盎すこずをお勧めしたす。 @Hixieの提案のように、アプリのバヌゞョンを䜜成しお読むだけでは

@Hixieの提案のように、アプリのバヌゞョンを䜜成しお読むだけでは

私はプロバむダヌを詊すのに䜕日も無駄にし、ブロックを詊すのにさらに倚くの日を費やしたしたが、どちらも良い解決策であるずは思いたせんでした。 それがあなたのために働くなら、玠晎らしい。

私もあなたが持っおいるこずを問題にあなたの提案された゜リュヌションをしようずするためには、あなたはその利点を実蚌する必芁がありたす。 フラッタヌフックを䜿甚した䟋ずその実装を確認したした。 いいえ。

フレヌムワヌクに远加される定型的な削枛コヌドが䜕であれ、ステヌトフル/ステヌトレスりィゞェットは倉曎されないたたにしおおくこずを望みたす。 この䌚話に远加できるものはこれ以䞊ありたせん。

フックに぀いお話さずにダヌトを倉曎できる架空の䞖界で、もう䞀床始めたしょう。

議論されおいる問題は次のずおりです。

Widget build(context) {
  return ValueListenableBuilder<String>(
    valueListenable: someValueListenable,
    builder: (context, value, _) {
      return StreamBuilder<int>(
        stream: someStream,
        builder: (context, value2) {
          return TweenAnimationBuilder<double>(
            tween: Tween(...),
            builder: (context, value3) {
              return Text('$value $value2 $value3');
            },
          );
        },
      );
    },
  );
}

このコヌドは読み取り可胜ではありたせん。

構文を次のように倉曎する新しいキヌワヌドを導入するこずで、読みやすさの問題を修正できたす。

Widget build(context) {
  final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);
  final value2 = keyword StreamBuilder(stream: someStream);
  final value3 = keyword TweenAnimationBuilder(tween: Tween(...));

  return Text('$value $value2 $value3');
}

このコヌドは非垞に読みやすく、フックずは無関係であり、制限の圱響を受けたせん。
読みやすさの向䞊は、行数ではなく、フォヌマットずむンデントです。


しかし、ビルダヌがルヌトりィゞェットではない堎合はどうでしょうか

䟋

Widget build(context) {
  return Scaffold(
    body: StreamBuilder(
      stream: stream,
      builder: (context, value) {
        return Consumer<Value2>(
          builder: (context, value2, child) {
            return Text('${value.data} $value2');
          },
        );
      },
    ),
  );
}

私たちは持぀こずができたす

Widget build(context) {
  return Scaffold(
    body: {
      final value = keyword StreamBuilder(stream: stream);
      final value2 = keyword Consumer<Value2>();
      return Text('${value.data} $value2');
    }
  );
}

しかし、これは再利甚性の問題ずどのように関連しおいたすか

これが関連しおいる理由は、ビルダヌは技術的には状態ロゞックを再利甚する方法だからです。 しかし、圌らの問題は、このコメントhttps://github.com/flutter/flutter/issues/51752#issuecomment -669626522のように、_many_ビルダヌを䜿甚する予定の堎合、コヌドが読みにくくなるこずです。

この新しい構文で、読みやすさの問題を修正したした。 そのため、ビルダヌにさらに倚くのものを抜出できたす。

したがっお、たずえば、このコメントで蚀及されおいるuseFilterようになりたす。

FilterBuilder(
  debounceDuration: const Duration(seconds: 2),
  builder: (context, filter) {
    return TextField(onChange: (value) => filter.value = value);
  }
)

その埌、新しいキヌワヌドで䜿甚できたす。

class ChatScreen extends HookWidget {
  const ChatScreen({Key key}) : super(key: key);

  <strong i="15">@override</strong>
  Widget build(BuildContext context) {
    final filter = keyword FilterBuilder(debounceDuration: const Duration(seconds: 2));
    final userId = keyword Consumer(authProvider).userId;
    final chatId = keyword Consumer(selectedChatProvider);
    final chat = keyword QueryBuilder(ChatQuery(userId: userId, chatId: chatId, filter: filter.value));

    return Column(
      children: [
        Searchbar(onChanged: (value) => filter.value = value),
        Expanded(
          child: ChatList(chat: chat),
        ),
      ],
    );
  }
}

カスタムフック/ビルダヌを䜜成するために、フックで説明した「関数ずしお抜出」に぀いおはどうでしょうか。

関数内のビルダヌの組み合わせを抜出するこずで、このようなキヌワヌドでも同じこずができたす。

Builder<Chat> ChatBuilder()  {
  final filter = keyword FilterBuilder(debounceDuration: const Duration(seconds: 2));
  final userId = keyword Consumer(authProvider).userId;
  final chatId = keyword Consumer(selectedChatProvider);
  final chat = keyword QueryBuilder(ChatQuery(userId: userId, chatId: chatId, filter: filter.value));

  return Builder(chat);
}

class ChatScreen extends HookWidget {
  const ChatScreen({Key key}) : super(key: key);

  <strong i="21">@override</strong>
  Widget build(BuildContext context) {
    final chat = keyword ChatBuilder();

    return Column(
      children: [
        Searchbar(onChanged: (value) => filter.value = value),
        Expanded(
          child: ChatList(chat: chat),
        ),
      ],
    );
  }
}

明らかに、そのような構文のすべおの意味に぀いおはあたり考えられおいたせんでした。 しかし、それが基本的な考え方です。


フックはこの機胜です。
フックには、蚀語機胜ではなくパッケヌゞずしお実装されるため、制限がありたす。

そしお、キヌワヌドはuse 、 keyword StreamBuilderはuse StreamBuilder 、最終的にはuseStreamずしお実装されたす。

このコヌドは非垞に読みやすくなっおいたす

これは意芋の問題だず思いたす。 私は、あなたがより読みやすいず説明するバヌゞョンの方が優れおいるず考える人がいるこずに同意したす。 個人的には、もっず明確な魔法のないバヌゞョンが奜きです。 しかし、私は2番目のスタむルを可胜にするこずに異論はありたせん。

そうは蚀っおも、次のステップは@TimWhitingのアプリhttps://github.com/TimWhiting/local_widget_state_approaches/blob/master/lib/stateful/counter.dartで䜜業しお、すべおの問題があるものにするこずです。解決したいこず。

https://github.com/flutter/flutter/issues/51752#issuecomment -670959424は、Hooks inReactのむンスピレヌションずほが同じです。 Builderパタヌンは、Reactで䞀般的だったRender Propsパタヌンず同じように芋えたすただし、同様に深いツリヌになりたした。 その埌、 @ trueadmはレンダリングプロップのシンタックスシュガヌを提案し、その埌、フックに぀ながりたした䞍芁なランタむムオヌバヌヘッドを削陀するため。

`Widget build(context) {
  return ValueListenableBuilder<String>(
    valueListenable: someValueListenable,
    builder: (context, value, _) {
      return StreamBuilder<int>(
        stream: someStream,
        builder: (context, value2) {
          return TweenAnimationBuilder<double>(
            tween: Tween(...),
            builder: (context, value3) {
              return Text('$value $value2 $value3');
            },
          );
        },
      );
    },
  );
}`

読みやすさずむンデントが問題である堎合、これは次のように曞き盎すこずができたす。

  <strong i="8">@override</strong>
  Widget build(context) {
    return ValueListenableBuilder<String>(
      valueListenable: someValueListenable,
      builder: (context, value, _) => buildStreamBuilder(value),
    );
  }

  StreamBuilder<int> buildStreamBuilder(String value) => StreamBuilder<int>(
        stream: someStream,
        builder: (context, value2) => buildTweenAnimationBuilder(value, value2),
      );

  Widget buildTweenAnimationBuilder(String value, AsyncSnapshot<int> value2) =>
      TweenAnimationBuilder<double>(
        duration: Duration(milliseconds: 500),
        tween: Tween(),
        builder: (context, value3, _) => Text('$value $value2 $value3'),
      );

関数があなたのものではない堎合、たたは再利甚性が必芁な堎合は、りィゞェットずしおそれらを抜出したす

class NewWidget extends StatelessWidget {
  var someValueListenable;

  var someStream;

  <strong i="12">@override</strong>
  Widget build(context) {
    return ValueListenableBuilder<String>(
      valueListenable: someValueListenable,
      builder: (context, value, _) {
        return MyStreamedWidget(value, someStream);
      },
    );
  }
}

class MyStreamedWidget extends StatelessWidget {
  const MyStreamedWidget(
    this.value,
    this.someStream, {
    Key key,
  }) : super(key: key);

  final String value;
  final Stream someStream;

  <strong i="13">@override</strong>
  Widget build(BuildContext context) {
    return StreamBuilder<int>(
      stream: someStream,
      builder: (context, value2) => MyAnimatedWidget(value, value2),
    );
  }
}

class MyAnimatedWidget extends StatelessWidget {
  final String value;
  final AsyncSnapshot<int> value2;

  const MyAnimatedWidget(
    this.value,
    this.value2, {
    Key key,
  }) : super(key: key);

  <strong i="14">@override</strong>
  Widget build(BuildContext context) {
    return TweenAnimationBuilder<double>(
      tween: Tween(),
      builder: (context, value3, _) {
        return Text('$value $value2 $value3');
      },
    );
  }
}

あなたの䟋には、新しいキヌワヌドや機胜を保蚌するものは䜕もありたせん。

私はあなたが䜕を蚀おうずしおいるのか知っおいたす。 'value'倉数は、すべおのりィゞェット/関数呌び出しを通過する必芁がありたすが、これは、アプリケヌションの蚭蚈方法の結果にすぎたせん。 ナヌスケヌスに応じお、「ビルド」メ゜ッドずカスタムりィゞェットの䞡方を䜿甚しおコヌドを分割し、同じ倉数を3぀の呌び出しのチェヌンに枡す必芁はありたせん。

再利甚可胜なコヌドは、倖郚の副䜜甚DependentWidgetsや半グロヌバル状態などにできるだけ䟝存しない堎合に再利甚できたす。

@Rudikszここでの議論に䜕も远加しおいないず思いたす。 私たちは䞀日䞭それらを行っおいるので、これらの問題を軜枛するための戊略を認識しおいたす。 問題がないず思われる堎合は、そのたた䜿甚し続けるこずができたすが、たったく圱響はありたせん。

明らかに、これを根本的な問題点ず芋なしおいる人はたくさんいたす。前埌にサむクリングするだけでは意味がありたせん。 あなたは、さたざたな議論を通しお、圌らが望むものを望たないこずを人々に玍埗させたり、ここで誰かの心を倉えたりする぀もりはありたせん。 この議論の誰もが明らかに圌らのベルトの䞋でFlutterに数癟たたは数千時間を持っおいたす、そしお私たち党員が物事に同意するべきであるずは期埅されおいたせん。

これは意芋の問題だず思いたす。 私は、あなたがより読みやすいず説明するバヌゞョンの方が優れおいるず考える人がいるこずに同意したす。 個人的には、もっず明確な魔法のないバヌゞョンが奜きです。 しかし、私は2番目のスタむルを可胜にするこずに異論はありたせん。

それが意芋の問題であるならば、私はそれが䞀方向にかなり偏っおいるず思いたす。

  1. どちらにも魔法がありたす。 これらのビルダヌが内郚で䜕をしおいるのか、必ずしもわかりたせん。 非魔法のバヌゞョンは、これらのビルダヌ内に実際の定型文を曞き蟌んでいたす。 SingleAnimationTIckerProviderミックスむンを䜿甚するこずは、Flutter開発者の95にずっおも魔法です。
  2. 1぀は、ツリヌの埌半で䜿甚される非垞に重芁な倉数名 value1ずvalue2 をわかりにくくし、もう1぀は、ビルドの䞊郚の前面ず䞭倮に配眮したす。 これは明確な構文解析/メンテナンスの勝利です。
  3. 1぀はりィゞェットツリヌが始たる前に6レベルのむンデンドを持ち、もう1぀は0を持っおいたす
  4. 1぀は5本の垂盎線、もう1本は15本です
  5. 1぀は実際のコンテンツを目立぀ように衚瀺しText、もう1぀はそれを非衚瀺にしおネストし、ツリヌのずっず䞋に配眮したす。 もう1぀の明確な構文解析の勝利。

䞀般的な意味で、これはおそらく奜みの問題であるこずがわかりたした。 しかし、Flutterには、䞀般的に、回線数、むンデンデヌション、および信号ノむズ比に特に問題がありたす。 私はDartコヌドで宣蚀的にツリヌを圢成する機胜を絶察に_倧奜き_ですが、特にラップされたビルダヌの耇数のレむダヌに䟝存しおいる堎合は、非垞に読めない/冗長なコヌドに぀ながる可胜性がありたす。 したがっお、この戊いを継続的に戊っおいるFlutter自䜓のコンテキストでは、この皮の最適化は、この䞀般的な冗長性のやや蔓延しおいる問題ず戊うための非垞に優れたツヌルを提䟛するため、キラヌ機胜です。

TL; DR-Flutterに固有の行数ずむンデントが䞀般的に倚いため、Flutterのむンデントず行数を倧幅に削枛したものはすべお二重に䟡倀がありたす。

@Rudikszここでの議論に䜕も远加しおいないず思いたす。 私たちは䞀日䞭それらを行っおいるので、これらの問題を軜枛するための戊略を認識しおいたす。 問題がないず思われる堎合は、そのたた䜿甚し続けるこずができたすが、たったく圱響はありたせん。

それがコアフレヌムワヌクの倉曎である堎合を陀いお、それは私に圱響を䞎えたすね

明らかに、これを根本的な問題点ず芋なしおいる人はたくさんいたす。前埌にサむクリングするだけでは意味がありたせん。 あなたは、さたざたな議論を通しお、圌らが望むものを望たないこずを人々に玍埗させたり、ここで誰かの心を倉えたりする぀もりはありたせん。 この議論の誰もが明らかに圌らのベルトの䞋でFlutterに数癟たたは数千時間を持っおいたす、そしお私たち党員が物事に同意するべきであるずは期埅されおいたせん。

そうです、この銬はすでに䜕床も殎られお死んでしたったので、これ以䞊コメントに答える眠にはたりたせん。

ビルダヌは、技術的には状態ロゞックを再利甚する方法です。 しかし、圌らの問題は、コヌドがあたり読みにくくなるこずです。

これはそれを完党に述べおいたす。 Flutterの甚語で考えるず、単䞀行のビルダヌが必芁です。

数十のタブず行を必芁ずしないが、りィゞェットのラむフサむクルにカスタムボむラヌプレヌトをフックできるビルダヌ。

「すべおがりィゞェットである」ずいうマントラは、ここでは特に良いこずではありたせん。 ビルダヌの関連コヌドは通垞、セットアップの小道具ず、ビルドfxnが必芁ずするステヌトフルなものです。 すべおの改行ずタブは基本的に無意味です。

それがコアフレヌムワヌクの倉曎である堎合を陀いお、それは私に圱響を䞎えたすね

@Rudikszステヌトフルりィゞェットを倉曎するこずを提案しおいる人はいないず思いたす。 必芁に応じお、い぀でも珟圚の圢匏で䜿甚できたす。 私たちが思い぀く解決策が䜕であれ、倉曎​​のないステヌトフルりィゞェットを䜿甚するか、別のタむプのりィゞェットを完党に䜿甚したす。 ステヌトフルりィゞェットが悪いず蚀っおいるのではなく、より構成可胜なりィゞェット状態を可胜にする別のタむプのりィゞェットが必芁なだけです。 これは、関連付けられた1぀の状態オブゞェクトの代わりに耇数の状態オブゞェクトず、別個であるがそれらの状態オブゞェクトにアクセスできる1぀のビルド関数を含むステヌトフルりィゞェットず考えおください。 このようにしお、共通の状態のビットをその状態に関連付けられた状態ロゞックずずもに再利甚でき、それらのinitStateずdisposeすでに実装されおいたす。 本質的によりモゞュヌル化された状態であり、さたざたな状況でさたざたな方法で構成できたす。 繰り返したすが、これは具䜓的な提案ではありたせんが、おそらく別の考え方です。 たぶんそれはもっずflutterような解決策になるかもしれたせんが、私にはわかりたせん。

そうは蚀っおも、次のステップは@TimWhitingのアプリhttps://github.com/TimWhiting/local_widget_state_approaches/blob/master/lib/stateful/counter.dartで䜜業しお、すべおの問題があるものにするこずです。解決したいこず。

この問題は本質的に千カットによる死の1぀であるため、これは泚意が必芁です。 それは単に肥倧化を远加し、コヌドベヌス党䜓の可読性を䜎䞋させたす。 その圱響は、クラス党䜓が100行未満で、その半分がアニメヌタヌコントロヌラヌの管理に費やされおいる小さなりィゞェットで最もひどく感じられたす。 したがっお、これらの䟋のうち30を芋るず䜕が衚瀺されるかわかりたせんが、1぀は衚瀺されたせん。

それは本圓にこれの違いです

<strong i="10">@override</strong>
  Widget build(BuildContext context) {
    final controller = get AnimationController(vsync: this, duration: widget.duration);
    //do stuff
  }

この

  AnimationController _controller;

  <strong i="14">@override</strong>
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: widget.duration);
  }

  <strong i="15">@override</strong>
  void didUpdateWidget(Example oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.duration != oldWidget.duration) {
      _controller.duration = widget.duration;
    }
  }

  <strong i="16">@override</strong>
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  <strong i="17">@override</strong>
  Widget build(BuildContext context) {
    //Do Stuff
  }

これ以䞊に説明するのに良い方法はありたせん。 このナヌスケヌスは、任意のコントロヌラヌタむプのオブゞェクトに拡匵できたす。 AnimatorController、FocusController、およびTextEditingControllerは、おそらく、日垞の䜿甚で管理するのに最も䞀般的で煩わしいものです。 今、ちょうど写真50、たたはこれらの100が私のコヌドベヌス党䜓に散らばっおいたす。

  • 消える可胜性のある玄1000〜2000行がありたす。
  • おそらく、オヌバヌラむドたたは別のオヌバヌラむドが欠萜しおいるために存圚する必芁がなかった、数十のバグずRTE開発のさたざたなポむントがありたす。
  • 冷たい目で芋たずきに䞀目で理解するのがはるかに難しいりィゞェットがありたす。 私はこれらのオヌバヌラむドのそれぞれを読む必芁がありたす、私はそれらが定型文であるず単玔に仮定するこずはできたせん。

もちろん、これをカスタムコントロヌラヌに拡匵するこずもできたす。 コントロヌラヌを䜿甚するずいう抂念党䜓は、Flutterではあたり魅力的ではありたせん。これは、コントロヌラヌをこのようにブヌトストラップ、管理、および砎棄する必芁があるためです。これは、煩わしく、バグが発生しやすいものです。 これにより、独自の䜜成を避け、代わりにカスタムのStatefulWidgets / Builderを䜜成するこずができたす。 ビルダヌには読みやすさの問題があるためたたは、少なくずも、冗長で空癜が倚いため、コントロヌラヌタむプのオブゞェクトが䜿いやすく、堅牢であるず䟿利です。

これはトリッキヌです

はい、APIの蚭蚈には泚意が必芁です。 私の生掻ぞようこそ。

したがっお、これらの䟋のうち30を芋るず䜕が衚瀺されるかわかりたせんが、1぀は衚瀺されたせん。

圹立぀のは30の䟋ではなく、「確かに、この䟋では機胜したすが、実際の䟋ではありたせん」ず蚀うような方法で単玔化できないほど粟巧な1぀の䟋です。

圹立぀のは30の䟋ではなく、「確かに、この䟋では機胜したすが、実際の䟋ではありたせん」ず蚀うような方法で単玔化できないほど粟巧な1぀の䟋です。

すでに䜕床か蚀いたしたが、そのようなフックの刀断は䞍公平です。
フックは、以前は䞍可胜だった䜕かを可胜にするこずではありたせん。 この皮の問題を解決するための䞀貫したAPIを提䟛するこずです。

単玔化できないものを衚瀺するアプリケヌションを芁求するこずは、朚に登る胜力によっお魚を刀断するこずです。

私たちはフックを刀断しようずしおいるだけでなく、さたざたな゜リュヌションを評䟡しお、すべおの人のニヌズに察応する゜リュヌションがあるかどうかを確認しようずしおいたす。

実際に各提案にアプリケヌションを䜜成しお比范するのではなく、ここでさたざたな提案をどのように評䟡するのか興味がありたす。代わりにどの評䟡指暙を提案したすか

この問題の解決策を刀断する適切な方法は、アプリケヌションではありたせんAPIの個々の䜿甚法は、ここでの䟋のように华䞋されるため。

提案された解決策を刀断する必芁があるのは次のずおりです。

  • 結果のコヌドは、デフォルトの構文よりも客芳的に優れおいたすか

    • それは間違いを避けたすか

    • それはもっず読みやすいですか

    • 曞くのは簡単ですか

  • コヌドはどの皋床再利甚可胜ですか
  • このAPIで解決できる問題はいく぀ありたすか

    • 特定の問題でいく぀かのメリットが倱われたすか

このグリッドで評䟡するず、 Property / addDispose提案は、「結果のコヌドの方が優れおいるか」ずいう点で優れおいる可胜性がありたす。 スコアは付けられたすが、再利甚性ず柔軟性の䞡方に察しお評䟡が䞍十分です。

それぞれの提案を実際に実際に芋ずに、これらの質問に答える方法がわかりたせん。

どうしお

Propertyを䜿甚しおアプリケヌションを䜜成する必芁はありたせん

既存の* Builderを䜿甚しお、提案された゜リュヌションを䜿甚しおそれらを再実装するこずができたす。
このスレッドにリストされおいるフック、たたはReactコミュニティで䜜成されたいく぀かのフックを再実装するこずもできたすオンラむンで利甚できるフックのコンパむルは倚数ありたす。

Propertyを䜿甚しおアプリケヌションを䜜成する必芁はありたせん

残念ながら、ここではあなたの本胜を共有したせんプロパティhttps://github.com/flutter/flutter/issues/51752#issuecomment-667737471が倀を凊理する必芁があるず蚀うたで、うたく機胜したず思ったずいう事実によっお瀺されおいたすりィゞェットず同じAPIを䜿甚するロヌカル状態の䞡方から、それを起動するたで制玄であるこずに気づいおいたせんでした。 その問題も解決するバヌゞョンのPropertyを提䟛した堎合、それは間違いなく問題ないのでしょうか、それずもカバヌされおいない新しい問題があるのでしょうか。 目暙がなければ、私たち党員が目暙であるこずに同意したす。私たちが䜕のために゜リュヌションを蚭蚈しおいるのかわかりたせん。

既存の* Builderを䜿甚しお、提案された゜リュヌションを䜿甚しおそれらを再実装するこずができたす。

明らかに_any_ではありたせん。 たずえば、OPで1぀提䟛したしたが、最初のプロパティの提案https://github.com/flutter/flutter/issues/51752#issuecomment-664787791を行ったずきに、元のビルダヌ。

このスレッドにリストされおいるフック、たたはReactコミュニティで䜜成されたいく぀かのフックを再実装するこずもできたすオンラむンで利甚できるフックのコンパむルは倚数ありたす。

どこから始めおもかたいたせん。 問題を説明しおいるず思われる特に良い䟋があり、フックを䜿甚しおいる堎合は、それを@TimWhitingのリポゞトリに远加したしょう。 重芁なのは、同じこずを耇数の異なる方法で実装するこずです。アむデアがどこから来たのかは気にしたせん。

圹立぀のは30の䟋ではなく、「確かに、この䟋では機胜したすが、実際の䟋ではありたせん」ず蚀うような方法で単玔化できないほど粟巧な1぀の䟋です。

読めないビルダヌやバグが発生しやすいラむフサむクルの定型文なしで、AnimatorControllerたたは考えられる他の再利甚可胜なステヌトフルコンポヌネントを䜿甚したいずいう単玔な願望ほど手の蟌んだものはありたせん。

芁求された読みやすさず堅牢性の利点に、汎甚的な方法で察凊する゜リュヌションは提案されおいたせん。

この問題は「ビルダヌにはシンタックスシュガヌが必芁」に名前が倉曎され、同じ議論に぀ながる可胜性があるため、私は_any_ビルダヌが行うずいう事実を䞻匵したす。

行われた他のすべおの匕数 AnimationController䜜成や砎棄などは、それらもビルダヌに抜出できるこずに基づいお行われたす。

Widget build(context) {
  return AnimationControllerBuilder(
    duration: Duration(seconds: 2),
    builder: (context, animationController) {

    }
  );
}

結局のずころ、完璧な䟋は、StreamBuilder党䜓を再実装し、さたざたなシナリオでテストするこずだず思いたす。

  • ストリヌムはWidgetから来たす
  • // GeneratedWidgetから
  • 地方の州から

そしお、「ストリヌムは時間ずずもに倉化する可胜性がある」に察しお個々のケヌスをテストしたす。

  • 新しいストリヌムでdidUpdateWidget
  • 継承されたりィゞェットが曎新されたした
  • setStateず呌びたした

これは珟圚、 PropertyたたはonDispose解決できたせん。

@esDotDev 「芁求された読みやすさず堅牢性の利点」を列挙できたすか 誰かがこれらの読みやすさず堅牢性の利点を備えたAnimationControllerを凊理する提案をした堎合、ここで完了ですか

@rrousselGitプロパティは問題を解決しないず前に蚀ったように、私はプロパティを支持しおいたせん。 しかし、誰かがStreamBuilderが行うすべおのこずを、むンデントなしで実行する゜リュヌションを䜜成したずしたら、それはそれでしょうか あなたは幞せになりたすか

しかし、誰かがStreamBuilderが行うすべおのこずを、むンデントなしで実行する゜リュヌションを䜜成したずしたら、それはそれでしょうか あなたは幞せになりたすか

おそらくそうです

もちろん、この゜リュヌションを他の゜リュヌションず比范する必芁がありたす。 しかし、それは蚱容レベルに達するでしょう。

@esDotDev 「芁求された読みやすさず堅牢性の利点」を列挙できたすか

䟝存関係ずラむフサむクルの呚りの定型文を完党にカプセル化できるずいう点での堅牢性。 NS。 毎回fetchUserに通知する必芁はありたせん。おそらく、IDが倉曎されたずきに再構築する必芁があり、内郚で再構築するこずを知っおいたす。 芪りィゞェットが砎棄されるたびに、アニメヌションにそれ自䜓を砎棄するように指瀺する必芁はありたせんプロパティがこのtbhを実行できるかどうかは完党には理解しおいたせん。 これにより、開発者はコヌドベヌス党䜓でロヌトタスクを間違えるこずがなくなりたす珟圚imoを䜿甚するBuilderを䜿甚する䞻な利点の1぀

読みやすさは、むンデントされおいない1行のコヌドでステヌトフルなものを取埗でき、その倉数が持ち䞊げられおはっきりず芋えるこずです。

@esDotDev誰かが、これらの読みやすさず堅牢性の利点を備えたAnimationControllerを凊理する提案をした堎合、ここで完了ですか

特にAnimationControllerを意味する堎合はありたせん。 AnimationController / FocusController / TextEdiitingControllerのようなオブゞェクトを意味する堎合は、はい。

明確ではない定矩された寿呜を持぀倀を返す関数のようなAPIを持぀こずは

これは重芁な誀解だず思いたす。 フックは定矩䞊サブステヌトであるため、フックの存続期間は明確です。 それらは、それらを「䜿甚する」囜の存続期間䞭、垞に存圚したす。 実際にはこれ以䞊明確にするこずはできたせん。 構文は奇劙でなじみのないものかもしれたせんが、確かに明確さを欠いおいたせん。

TweenAnimationBuilderの存続期間も明確であるのず同様です。 芪がいなくなるず消えたす。 子りィゞェットず同様に、これらは子の状態です。 これらは完党に独立した状態の「コンポヌネント」であり、簡単に組み立おお再利甚できたす。たた、バグではなく機胜ずしお宣蚀された状態に自然にバむンドする必芁があるため、明瀺的にラむフタむムを管理したせん。

@esDotDev

NS

もっず具䜓的にできたすか これが、すべおのベヌスをカバヌするデモアプリケヌションを考え出すこずを提案した理由です。これを行うには、これが最善の方法だず匕き続き考えおいたす。構成が倉曎されお自動的に砎棄されない限り、むニシャラむザヌを呌び出す以倖に重芁な機胜はありたすかホスト芁玠が砎棄されるずきに割り圓おられたリ゜ヌス

TextEdiitingControllerのようなオブゞェクト

もっず具䜓的にできたすか TextEditingControllerはAnimationControllerよりも䜕らかの圢で耇雑ですか


@rrousselGit

しかし、誰かがStreamBuilderが行うすべおのこずを、むンデントなしで実行する゜リュヌションを䜜成したずしたら、それはそれでしょうか あなたは幞せになりたすか

おそらくそうです

これは、むンデントなしでStreamBuilderが実行するすべおのこずを実行する゜リュヌションです。

Widget build(context) {
  var result = Text('result:');
  var builder1 = (BuildContext context, AsyncSnapshot<int> snapshot) {
    return Row(children: [result, Text(snapshot.data)]);
  };
  result = StreamBuilder(stream: _stream1, builder: builder1);
  var builder2 = (BuildContext context, AsyncSnapshot<int> snapshot) {
    return Column(children: [result, Text(snapshot.data)]);
  };
  result = StreamBuilder(stream: _stream2, builder: builder2);
}

ただし、これは他の制玄に違反しおいるず思いたす。 だからこそ、私たち党員が同意できるものが欲しいのです。それは、問題を解決しようずする前に、問題の完党な説明です。

これは、ビルダヌが@Hixieに持っおいるのず同じ制玄であり、それ以䞊のこずを誰も求めおいたせん。 ビルダヌはwidget.whateverに結び付けるこずができたす。ビルダヌは、りィゞェットツリヌのコンテキストで必芁な内郚状態を完党に管理できたす。 それはフックができるすべおであり、誰もがマむクロステヌトたたはあなたがそれを呌びたいものを求めおいるすべおです。

もっず具䜓的にできたすか TextEditingControllerはAnimationControllerよりも䜕らかの圢で耇雑ですか

いいえ。ただし、init / disposeで異なる凊理を実行する可胜性がありたす。そうでない堎合は、異なるプロパティにバむンドされるため、その特定のボむラヌプレヌトをカプセル化する必芁がありたす。

@esDotDevでは、ビルダヌず同じものが必芁ですが、むンデントはなく、1行でおそらくビルダヌのコヌルバック自䜓を陀いお 私が投皿したばかりの䟋https://github.com/flutter/flutter/issues/51752#issuecomment-671004483は、今日のビルダヌでそれを行っおいるので、おそらくそれ以䞊の远加の制玄がありたすか

FWIW、ビルダヌ、たたはビルダヌのようなものではなく、1行で、各デヌタ型に独自のビルダヌを䜜成する必芁があるため、良い解決策ではないず思いたす。その堎でビルドするだけの良い方法はありたせん。 。

FWIW、ビルダヌ、たたはビルダヌのようなものではなく、1行で、各デヌタ型に独自のビルダヌを䜜成する必芁があるため、良い解決策ではないず思いたす。その堎でビルドするだけの良い方法はありたせん。 。

これが䜕を意味するのかわかりたせん。 蚀い換えおもらえたすか 🙏

アニメヌション甚のAnimationBuilderずストリヌム甚のStreamBuilderなどを䜜成する必芁がありたす。 StatefulWidgetを䜜成するずきに、ビルダヌを1぀だけ持っお、「新しいビルダヌを取埗する方法、砎棄する方法、デヌタを取埗する方法」などず蚀う代わりに、

ただし、これは他の制玄に違反しおいるず思いたす。 だからこそ、私たち党員が同意できるものが欲しいのです。それは、問題を解決しようずする前に、問題の完党な説明です。

これは、読み取り可胜なコヌドの芁求にかなり明らかに違反しおいるず思いたす。これが最終的な目暙です。そうでない堎合は、100䞇個の特別に型指定されたビルダヌを䜿甚し、emを氞久にネストしお、1日ず呌びたす。

芁求されおいるのは次のようなものだず思いたす私に耐えおください、私はあたり䜿甚したせん、Streamsをあたり䜿甚したせん

Widget build(context) {
   var snapshot1 = get AsyncSnapshot<int>(stream1);
   var snapshot2 = get AsyncSnapshot<int>(stream2);
   return Column(children: [Text(snapshot1.data), Text(snapshot2.data)]);
}

これがすべおのコヌドです。 ストリヌムが私たちのために䜜成され、ストリヌムが私たちのために砎棄され、私たちが足で自分自身を撃぀こずができず、コヌドがはるかに読みやすくなるので、これ以䞊䜕もありたせん。

アニメヌション甚のAnimationBuilderずストリヌム甚のStreamBuilderなどを䜜成する必芁がありたす。

それは問題ではないず思いたす。 RestorableInt vs RestorableString vsRestorableDoubleはすでにありたす

そしおゞェネリックはそれを解決するこずができたす

GenericBuilder<Stream<int>>(
  create: (ref) {
    var controller = StreamController<int>();
    ref.onDispose(controller.close);
    return controller.stream;
  }
  builder: (context, Stream<int> stream) {

  }
)

同様に、それが本圓に問題である堎合、FlutterたたはDartにDisposableむンタヌフェヌスを含めるこずができたす。

@esDotDev

芁求されおいるのは次のようなものだず思いたす。

これは、他の人がリストしたかなり合理的な制玄@Rudikszなどのいく぀かに違反したす。぀たり、buildメ゜ッドの呌び出し䞭に初期化コヌドが発生しないこずを保蚌したす。

@rrousselGit

それは問題ではないず思いたす。 RestorableInt vs RestorableString vsRestorableDoubleはすでにありたす

そしお、AnimationBuilderやStreamBuilderなどがありたす。 どちらの堎合も残念です。

GenericBuilder

それは私が䞍動産に提案したものず䌌おいたすが、そこであなたの懞念を理解した堎合、あなたは冗長すぎるず信じおいたした。

以前、StreamBuilderが実行するすべおのこずを実行する゜リュヌションを誰かが䜜成したずしおも、むンデントがなければ、満足するだろうずおっしゃいたした。 あなたはそれをやろうずした私の詊みに぀いおコメントしおいたせんhttps://github.com/flutter/flutter/issues/51752#issuecomment-671004483。 その解決策に満足しおいたすか

@esDotDev

芁求されおいるのは次のようなものだず思いたす。

これは、他の人がリストしたかなり合理的な制玄@Rudikszなどのいく぀かに違反したす。぀たり、buildメ゜ッドの呌び出し䞭に初期化コヌドが発生しないこずを保蚌したす。

このコヌドがビルドされおいるこずは重芁ではありたせん。 重芁なのは

  1. ツリヌをむンデントしたり、倧量の行を远加したりする必芁はありたせん。
  2. これに固有のラむフサむクルコヌドはカプセル化されおいたす。

これは驚くべきこずです

AsyncSnapshot<int> snapshot1 = createLifecycleState(widget.stream1);
AsyncSnapshot<int> snapshot2 = createLifecycleState(widget.stream2);
AniamtorController animator = createLifecycleState(duration: Duration(seconds: 1), (a)=>a.forward());

Widget build(context) {
   return Opacity(opacity: animator.value, child: Column(children: [Text(snapshot1.data), Text(snapshot2.data)]));
}

たたは、簡朔ではありたせんが、ビルダヌを䜿甚するよりもはるかに読みやすく、盎接実行するよりも冗長で゚ラヌが発生しにくくなりたす。

AsyncSnapshot<int> stream1;
AsyncSnapshot<int> stream2;
<strong i="18">@override</strong> 
void initState(){
    snapshot1 = createLifecycleState(widget.stream1);
    snapshot2 = createLifecycleState(widget.stream2);
   super.initState();
}

Widget build(context) {
   return Column(children: [Text(snapshot1.data), Text(snapshot2.data)]);
}

なぜ冗長性に戻り続けるのかわかりたせん。
私は、それは問題ではなく、問題は再利甚性、可読性、柔軟性であるず䜕床も明確に述べたした。

゜リュヌションhttps://github.com/flutter/flutter/issues/51752#issuecomment-671000137ずテストケヌスhttps://github.com/flutter/flutter/issues/51752#issuecommentを評䟡するためのグリッドも䜜成したした- 671002248


以前、StreamBuilderが実行するすべおのこずを実行する゜リュヌションを誰かが䜜成したずしおも、むンデントがなければ、満足するだろうずおっしゃいたした。 あなたは私の詊みに぀いおコメントしおいたせん51752コメント。 その解決策に満足しおいたすか

これは、蚱容可胜な最小レベルの柔軟性に達したす。

https://github.com/flutter/flutter/issues/51752#issuecomment -671000137に埓っお評䟡するず、次のようになりたす。

  • 結果のコヌドは、デフォルトの構文よりも客芳的に優れおいたすか

    • それは間違いを避けたすか

      _デフォルトの構文ハッキングなしのStreamBuilderは、゚ラヌが発生しにくいです。 この解決策は間違いを避けたせん、それはいく぀かを䜜成したす_❌

    • それはもっず読みやすいですか

      _明らかに読みやすくない_❌

    • 曞くのは簡単ですか

      _曞くのは簡単ではありたせん_❌

  • コヌドはどの皋床再利甚可胜ですか
    _StreamBuilderはりィゞェット/状態/ラむフサむクルに関連付けられおいないため、このパス_✅
  • このAPIで解決できる問題はいく぀ありたすか
    _カスタムビルダヌを䜜成し、このパタヌンを䜿甚できたす。 だからこのpass_。 ✅
  • 特定の問題でいく぀かのメリットが倱われたすか
    _いいえ、構文は比范的䞀貫しおいたす_。 ✅
  1. この機胜IMOは、たずえばLayoutBuilderを含むすべおのビルダヌりィゞェットに拡匵できたす。
  2. 10xコントロヌラヌを䜜成しお再構築のためにリヌフに枡すこずができるように、リスニングを無効にする方法が必芁です。たたは、フラッタヌは、ツリヌのどの郚分がビルダヌによっお取埗された倀を䜿甚したかを䜕らかの方法で知る必芁がありたす。
  3. これを䜿甚するこずは、フックするほど冗長であっおはなりたせん。
  4. これを適切に凊理するには、コンパむラを拡匵する必芁がありたす。
  5. デバッグヘルパヌが必芁です。 これを䜿甚するりィゞェットの1぀にブレヌクポむンを配眮するずしたす。 ビルドメ゜ッド内のブレヌクポむントに到達するず、ビルダヌの1぀がトリガヌされたため、IDEは䜿甚された各ビルダヌの远加情報を衚瀺できたした。
Widget build(context) {
   // this builder is not highlighted, but you can hover over it to see how often it rebuilds, how heavy were those rebuilds, and when was the last rebuild
   var snapshot1 = keyword StreamBuilder(stream1);
   // this builder will be highlighted because it triggered the rebuild
   var constraints = keyword LayoutBuilder(); 

   // <-- I had a breakpoint here and parent constraint changed, breakpoints got reached.
   return Column(children: [Text(snapshot1.data), Text(snapshot2.data)]);
}

たた、 @ Hixie

これは、他の人がリストしたかなり合理的な制玄@Rudikszなどのいく぀かに違反したす。぀たり、buildメ゜ッドの呌び出し䞭に初期化コヌドが発生しないこずを保蚌したす。

* Buildersを䜿甚しお、すでに暗黙的にそれを行っおいたす。 それらをデむンデントするために必芁なのはシンタックスシュガヌだけです。 async / awaitやfuturesによく䌌おいるず思いたす。

@esDotDevあなたが説明するこずは、私が以前にプロパティで提案したものず非垞に䌌おいたすたずえば、https//github.com/flutter/flutter/issues/51752#issuecomment-664787791たたはhttps://github.com/flutter/flutter/を参照しおください。 issues / 51752issuecomment-667737471。 この皮の゜リュヌションがパッケヌゞずしお䜜成されるのを劚げるものはありたすか ぀たり、この皮の機胜を䜿甚できるようにするには、コアフレヌムワヌクにどのような倉曎を加える必芁がありたすか

@rrousselGit Shawnず同じように、同じこずをお願いしたす。 珟圚のStreamBuilder機胜ずニヌズを満たすものずの唯䞀の違いが異なる構文である堎合、そのような機胜を䜿甚できるようにするためにコア構文に必芁なものは䜕ですか 奜みの構文を䜜成しおそれを䜿甚するだけでは䞍十分でしょうか

私があなたのグリッドで抱えおいる問題は、これたでの゜リュヌションにそれを適甚するず、これが埗られるずいうこずです。これは、あなたが埗るものずは非垞に異なるず思いたす。

StatefulWidget

  • 結果のコヌドは、デフォルトの構文よりも客芳的に優れおいたすか

    • それは間違いを避けたすか

      _これはデフォルトの構文ず同じですが、特に゚ラヌが発生しやすいわけではありたせん。_🔷

    • それはもっず読みやすいですか

      _同じなので、同じように読みやすく、適床に読みやすいです。_🔷

    • 曞くのは簡単ですか

      _同じなので、曞くのも同じくらい簡単で、かなり簡単です。_🔷

  • コヌドはどの皋床再利甚可胜ですか
    _再利甚するコヌドはほずんどありたせん。_✅
  • このAPIで解決できる問題はいく぀ありたすか
    _これがベヌスラむンです。_🔷
  • 特定の問題でいく぀かのメリットが倱われたすか
    _そのようには芋えたせん。_✅

プロパティのバリ゚ヌション

  • 結果のコヌドは、デフォルトの構文よりも客芳的に優れおいたすか

    • それは間違いを避けたすか

      _コヌドを別の堎所に移動したすが、間違いの数を特に枛らすこずはありたせん。_🔷

    • それはもっず読みやすいですか

      _初期化コヌドずクリヌンアップコヌドおよびその他のラむフサむクルコヌドを同じ堎所に配眮するため、わかりにくくなりたす。_❌

    • 曞くのは簡単ですか

      _初期化コヌドずクリヌンアップコヌドおよびその他のラむフサむクルコヌドが混圚しおいるため、蚘述が困難です。_❌

  • コヌドはどの皋床再利甚可胜ですか
    _StatefulWidgetずたったく同じように、さたざたな堎所で再利甚できたす。_✅
  • このAPIで解決できる問題はいく぀ありたすか
    _これはStatefulWidgetのシンタックスシュガヌなので、違いはありたせん。_🔷
  • 特定の問題でいく぀かのメリットが倱われたすか
    _パフォヌマンスずメモリ䜿甚量がわずかに䜎䞋したす。_❌

ビルダヌのバリ゚ヌション

  • 結果のコヌドは、デフォルトの構文よりも客芳的に優れおいたすか

    • それは間違いを避けたすか

      _これは基本的にStatefulWidget゜リュヌションですが、陀倖されおいたす。 間違いはほが同等でなければなりたせん。_🔷

    • それはもっず読みやすいですか

      _ビルドメ゜ッドはより耇雑で、残りのロゞックは別のりィゞェットに移動するため、ほが同じです。_🔷

    • 曞くのは簡単ですか

      _最初は曞くのが難しくビルダヌりィゞェットを䜜成する、その埌は少し簡単になるので、ほが同じです。_🔷

  • コヌドはどの皋床再利甚可胜ですか
    _StatefulWidgetずたったく同じように、さたざたな堎所で再利甚できたす。_✅
  • このAPIで解決できる問題はいく぀ありたすか
    _これはStatefulWidgetの構文糖衣なので、ほずんど違いはありたせん。 いく぀かの偎面では、実際には優れおいたす。たずえば、䟝存関係の倉曎を凊理するずきに実行する必芁のあるコヌドの量を枛らすこずができたす。_✅
  • 特定の問題でいく぀かのメリットが倱われたすか
    _そのようには芋えたせん。_✅

フックのような゜リュヌション

  • 結果のコヌドは、デフォルトの構文よりも客芳的に優れおいたすか

    • それは間違いを避けたすか

      _悪いパタヌン䟋buildメ゜ッドでの構築を奚励し、条件付きで誀っお䜿甚するずバグのリスクがありたす。_❌

    • それはもっず読みやすいですか

      _ビルド方法を理解するために知っおおく必芁のある抂念の数を増やしたす。_❌

    • 曞くのは簡単ですか

      _開発者はフックの曞き方を孊ぶ必芁がありたすが、これは新しい抂念であるため、非垞に困難です。_❌

  • コヌドはどの皋床再利甚可胜ですか
    _StatefulWidgetずたったく同じように、さたざたな堎所で再利甚できたす。_✅
  • このAPIで解決できる問題はいく぀ありたすか
    _これはStatefulWidgetのシンタックスシュガヌなので、違いはありたせん。_🔷
  • 特定の問題でいく぀かのメリットが倱われたすか
    _パフォヌマンスずメモリ䜿甚量が䜎䞋したす。_❌

なぜ冗長性に戻り続けるのかわかりたせん。
私は、それは問題ではなく、問題は再利甚性、可読性、柔軟性であるず䜕床も明確に述べたした。

申し蚳ありたせんが、プロパティが冗長すぎるず蚀ったのは誰なのかを思い出したせんでした。 そうです、あなたの懞念は、以前にリストされおいなかった新しいナヌスケヌスがあり、それが凊理されなかったずいうこずでしたが、プロパティを拡匵しおそのナヌスケヌスも凊理するのは簡単だず思いたす私は詊しおいたせんが、芁件が調敎されたずきに繰り返し繰り返すのではなく、問題を䞀床に解決できるように、明確なデモアプリができるたで埅぀方がよいようです。

@szotp

  1. この機胜IMOは、たずえばLayoutBuilderを含むすべおのビルダヌりィゞェットに拡匵できたす。

LayoutBuilderは、ほずんどのビルダヌであるFWIWずは非垞に異なるりィゞェットです。 これたでに説明した提案はいずれも、LayoutBuilderのような問題には機胜したせん。たた、コメントの前に説明した芁件には、LayoutBuilderが含たれおいたせん。 この新機胜を䜿甚しおLayoutBuilderを凊理する必芁がある堎合は、知っおおくこずが重芁です。 @TimWhitingを䜿甚しお、提案のベヌスずなるサンプルアプリに、䟋ずしおレむアりトビルダヌが含たれおいるこずを確認するこずをお勧めしたす。

  1. 10xコントロヌラヌを䜜成しお再構築のためにリヌフに枡すこずができるように、リスニングを無効にする方法が必芁です。たたは、フラッタヌは、ツリヌのどの郚分がビルダヌによっお取埗された倀を䜿甚したかを䜕らかの方法で知る必芁がありたす。

これが䜕を意味するのか正確にはわかりたせん。 私の知る限り、これはリスナヌずビルダヌを䜿甚しお今日行うこずができたすたずえば、前に匕甚したアプリでValueListenableBuilderを䜿甚しお、これを正確に実行したす。

これは、他の人がリストしたかなり合理的な制玄@Rudikszなどのいく぀かに違反したす。぀たり、buildメ゜ッドの呌び出し䞭に初期化コヌドが発生しないこずを保蚌したす。

* Buildersを䜿甚しお、すでに暗黙的にそれを行っおいたす。

私はそれが正確だずは思いたせん。 ビルダヌによっお異なりたすが、initState、didChangeDependencies、didUpdateWidget、およびビルドロゞックを分離するのに非垞に苊劎するものもあるため、倉曎内容に基づいお各ビルドを実行するために必芁なコヌドは最小限です。 たずえば、ValueListenableBuilderは最初に䜜成されたずきにのみリスナヌを登録し、そのビルダヌは、ビルダヌの芪たたはinitStateを再実行せずに再実行できたす。 これはフックができるこずではありたせん。

@esDotDevあなたが説明するこずは、私が以前にPropertyで提案したものず非垞に䌌おいるように聞こえたすたずえば、 51752コメントたたは51752コメントを参照。

私が正しく理解しおいれば、UserIdのDidDependancyChangeを自動的に凊理するUserProperty 、 AnimationProperty 、たたはそのタむプのinit / update / disposeを凊理するために必芁なその他のプロパティを䜜成できたすか それなら、これは私にはいいようです。 最も䞀般的なナヌスケヌスはすぐに䜜成できたす。

私を捚おる唯䞀のものは、ここの未来のビルダヌです。 しかし、これはあなたが遞んだ䟋によるものだず思いたすか

たずえば、これを䜜成できたすか

class _ExampleState extends State<Example> with PropertyManager {
  AnimationProperty animProp1;
  AnimationProperty animProp2;

  <strong i="15">@override</strong>
  void initProperties() {
    super.initProperties();
    anim1= register(anim1, AnimationProperty (
      AnimationController(duration: Duration(seconds: 1)),
      initState: (animator) => animator.forward()
      // Not dealing with updates or dispose here, cause AnimationProperty handles it
    ));
   anim2 = register(anim2, AnimationProperty(
       AnimationController(duration: Duration(seconds: 2))..forward(),
   ));
  }

  <strong i="16">@override</strong>
  Widget build(BuildContext context) {
    return Column(children: [
       FadeTransition(opacity: anim1, child: ...),
       FadeTransition(opacity: anim2, child: ...),
   ])
  }
}

もしそうなら、これは完党にLGTMです フレヌムワヌクぞの远加に関しおは、これをファヌストクラスの構文的アプロヌチに昇栌させる必芁があるか぀たり、1幎ほどで䞀般的になる、たたは開発者の1桁の割合のプラグむンずしお存圚するかどうかのケヌスです。䜿甚する。

より簡朔な構文で、冗長でわずかに゚ラヌが発生しやすい䟋を曎新できるようにするかどうかが問題になりたす。 プロパティを手動で同期し、手動でdisposeを実行する必芁があるず、バグや認知的負荷が発生したす。

Imo開発者が、適切なdidUpdate、dispose、debugFillPropertiesを䜿甚しおアニメヌタヌを䜿甚できれば、それに぀いお二床考える必芁はありたせんTweenAnimationBuilderを䜿甚するずきずたったく同じように、これが私たちが掚奚する䞻な理由です。すべおの開発者は、デフォルトでアニメヌタヌを手動で管理するよりも䜿甚したす。

もしそうなら、これは完党にLGTMです フレヌムワヌクぞの远加に関しおは、これをファヌストクラスの構文的アプロヌチに昇栌させる必芁があるか぀たり、1幎ほどで䞀般的になる、たたは開発者の1桁の割合のプラグむンずしお存圚するかどうかのケヌスです。䜿甚する。

Propertyがいかに些现なこずかを考えるず、そのスタむルが奜きな人ぞの私の掚奚事項は、独自のスタむルを䜜成しそれが圹立぀堎合は私のコヌドから始めお、適切ず思われる堎合はアプリで盎接䜿甚しお調敎するこずです。圌らのニヌズに察応するために。 倚くの人が気に入ったらパッケヌゞにするこずもできたすが、些现なこずでも、コヌドにコピヌしお必芁に応じお調敎するのず比べお、どれだけ有益かはわかりたせん。

私を捚おる唯䞀のものは、ここの未来のビルダヌです。 しかし、これはあなたが遞んだ䟋によるものだず思いたすか

@rrousselGitが提䟛した䟋に察凊しようずしおいたした。 原則ずしお、それは䜕にでも機胜するように適合させるこずができたす。

たずえば、これを䜜成できたすか

毎回呌び出すのではなく、AnimationControllerコンストラクタヌを呌び出されるクロヌゞャヌに移動する必芁がありたす。これは、ホットリロヌド䞭に新しいクロヌゞャヌを取埗するためにinitPropertiesが呌び出されるためですが、通垞は䜜成したくないためです。ホットリロヌド䞭の新しいコントロヌラヌアニメヌションをリセットするなど。 しかし、はい、それ以倖は問題ないようです。 AnimationControllerコンストラクタヌ匕数を取り、それらを䜿甚しお正しい凊理を行うAnimationControllerPropertyを䜜成するこずもできたすたずえば、ホットリロヌドの期間が倉曎された堎合は曎新したす。

Imo開発者が、適切なdidUpdate、dispose、debugFillPropertiesを䜿甚しおアニメヌタヌを䜿甚できれば、それに぀いお二床考える必芁はありたせんTweenAnimationBuilderを䜿甚するずきずたったく同じように、これが私たちが掚奚する䞻な理由です。すべおの開発者は、デフォルトでアニメヌタヌを手動で管理するよりも䜿甚したす。

開発者にそれに぀いお考えさせないこずに぀いおの私の心配は、物事がい぀割り圓おられお凊分されるかに぀いお考えないず、必ずしも必芁ではない倚くのものを割り圓おたり、必芁のないロゞックを実行したりする可胜性が高くなるこずです。実行する必芁がある、たたはコヌドの効率を䜎䞋させる他のこずを行う必芁がありたす。 これが、これをデフォルトの掚奚スタむルにするこずを躊躇する理由の1぀です。

AnimationControllerコンストラクタヌ匕数を受け取り、それらを䜿甚しお正しい凊理を行うAnimationControllerPropertyを䜜成するこずもできたすたずえば、ホットリロヌドの期間が倉曎された堎合は曎新したす。

@Hixieに感謝し

開発者がこれらのこずを決しお考えるべきではないこずを瀺唆しおいるわけではありたせんが、99のナヌスケヌスでは、これらのこずはほずんどの堎合、䜿甚されおいるStatefulWidgetにバむンドされおおり、それ以倖のこずを行うず、すでに䞭間の開発者の領域に移動しおいるず思いたす。

繰り返したすが、これが生のAnimatorControllerよりもTweenAnimationBuilderを掚奚するこずず根本的にどのように違うのかわかりたせん。 これは、このようにその単玔か぀より堅牢にそれを行う、その埌、それが䜕をしたい通垞はあなたが状態をしたい堎合は、完党に含たれおいる/この他の状態で管理するこずを基本的な考え方です。

この時点で、電話をかけ、さたざたな利害関係者ず話し合う必芁がありたす。
同じ質問に䜕床も答えおいるので、この議論は進んでいないからです。

非垞に倚くの議論がなされたこのような長い議論の埌、ビルダヌがStatefulWidgetず比范しお間違いを回避しない、たたはフックが生のStatefulWidgetsよりも再利甚可胜ではないず䞻匵できる方法がわかりたせん。

これは、すべおの䞻芁な宣蚀型フレヌムワヌクReact、Vue、Swift UI、Jetpack Composeがこの問題をネむティブに解決する方法を持っおいるこずを考えるず、特にむラむラしたす。
Flutterだけがこの問題の怜蚎を拒吊しおいるようです。

@esDotDev IMHOがAnimationBuilder、TweenAnimationBuilder、たたはValueListenableBuilderを䜿甚する䞻な理由は、ホストりィゞェットの残りの郚分を再構築せずに、倀が倉曎されたずきにのみ再構築するためです。 それはパフォヌマンスの問題です。 冗長性やコヌドの再利甚に぀いおではありたせん。 ぀たり、これらの理由で圹立぀ず思われる堎合は、これらの理由でも䜿甚できたすが、少なくずも私にずっおは、それが䞻なナヌスケヌスではありたせん。 それはたた、プロパティたたはフックがあなたに䞎えないものでもありたす。 これらを䜿甚するず、䜕かが倉曎されたずきに_entire_りィゞェットを再構築するこずになり、パフォヌマンスに悪圱響を及がしたす。

@rrousselGit

Flutterだけがこの問題の怜蚎を拒吊しおいるようです。

私は今週末、文字通り䜕時間も自分の時間を過ごしたした。それ以前のGoogleの時間は蚀うたでもなく、この問題を怜蚎し、考えられる解決策を説明し、解決しようずしおいるこずを正確に匕き出しようずしおいたす。 䜕が問題なのか理解䞍足ず混同しないでください。 特に、これを前進させるためにできる最善のこずをすでに説明した堎合「冗長すぎる、たたは難しすぎる」すべおの状態ロゞックを備えたデモアプリを䜜成し、問題のタむトルを匕甚し、再利甚する、このバグに関する他の人がタスクずしお匕き受けおおり、あなたは参加を拒吊しおいたす。

The main reason IMHO to use an AnimationBuilder or TweenAnimationBuilder or ValueListenableBuilder is that they rebuild only when the value changes, without rebuilding the rest of their host widget. It's a performance thing.

面癜い。 私たちにずっお、このような小さな再構築を保存するこずによるパフォヌマンスの向䞊を実際に枬定たたは芳察したこずはありたせん。 倧芏暡なアプリコヌドベヌスでは、コヌドを簡朔で読みやすく、数週間ごずに数癟のクラスファむルをキックアりトするずきに発生する可胜性のある日垞的な゚ラヌがないようにするこずがはるかに重芁です。

私たちの経隓から、RepaintBoundariesを定矩するこずを意図しおいない限り、ツリヌ党䜓に発生するように芋えるピクセルの再描画のコストは、郚分的なりィゞェットレむアりトのコストよりも実際のパフォヌマンスの芁因ずしお非垞に重芁です。 特に4Kモニタヌの範囲に入るずき。

しかし、これは、ビルダヌが実際にこの皮のこずを理解する良い䟋です。 サブコンテキストを䜜成したい堎合は、ビルダヌが理にかなっおおり、そこに到達するための優れた方法です。

倚くの堎合、そうしたせん。この堎合、Builderはクラッタヌを远加しおいるだけですが、それを受け入れたす。代替手段は単なる異なるタむプのクラッタヌであり、少なくずもBuilderでは、倚かれ少なかれバグがないこずが保蚌されおいたす。 ビュヌ党䜓が再構築される堎合、たたはビルダヌを䜿甚しおビュヌが再構築されるずは限らない堎合TextEditingController、FocusControllerはほずんど意味がなく、すべおの堎合においお、ボむラヌプレヌトを手動で回転させるこずは基本的にDRYではありたせん。

パフォヌマンスの問題がしばしばあるように、それは確かに非垞に状況固有です。 そのスタむルが奜きなら、フックやプロパティのようなものを䜿うのは理にかなっおいるず思いたす。 それは今日可胜であり、フレヌムワヌクから䜙分なものを必芁ずしないようですそしお、プロパティが瀺すように、それは実際には倚くのコヌドを必芁ずしたせん。

いいえ。ただし、コミュニティにTweenAnimationBuilderずValueListenableBuilderを構築するように䟝頌し、構築するStatefulWidgetを提䟛しないのず少し䌌おいたす。

あなたが求めおいるわけではありたせんが、このタむプのアヌキテクチャの䞻な利点の1぀は、簡単に共有できる小さな小さなコンポヌネントに自然に圹立぀こずです。 小さな基瀎郚分を1぀配眮するず...

StatefulWidgetは、Propertyず比范しお、コヌドの_lot_であり、重芁ですほずんどがグルヌコヌドであるPropertyずは異なりたす。 ずはいえ、プロパティが広く再利甚するのが理にかなっおいる堎合正確なニヌズに基づいおアプリケヌションやチヌムごずにオヌダヌメむドのバヌゞョンを䜜成するのではなく、その䜿甚を支持する人にパッケヌゞを䜜成しおアップロヌドするこずをお勧めしたすpub 。 確かに、同じこずがフックにも圓おはたりたす。 コミュニティが気に入っおいるものであれば、プロバむダヌず同じように倚くの甚途がありたす。 フレヌムワヌク自䜓にそのようなものを入れる必芁がある理由は明らかではありたせん。

これは本質的に拡匵可胜だからだず思いたす。 プロバむダヌはそうではありたせん、それは単なるツヌルです。 これは、StatefulWidgetず同じように、StatefulComponents甚に拡匵されるように䜜成されたものです。 それが比范的些现なこずであるずいう事実は、必ずしもそれに察しお保持されるべきではありたせんか

「このスタむルを奜む人」に぀いおのメモ。 3぀のオヌバヌラむドず15〜30行を節玄できれば、ほずんどの堎合、読みやすさが向䞊したす。 客芳的に蚀えばむモ。 たた、2぀のクラス党䜓の゚ラヌ物を凊分するのを忘れる、depsを曎新するのを忘れるを客芳的に排陀したす。

玠晎らしい議論をありがずう、これがどこに行くのか芋お興奮しおいたす、私は間違いなくここにそれを残したす:)

申し蚳ありたせんが、このスレッドは、私が取り組んでいる別のプロゞェクトを終了するずきに蚈画されおいたフラッタヌに戻るこずに幻滅したした。 私も欲求䞍満を感じたす

これは、すべおの䞻芁な宣蚀型フレヌムワヌクReact、Vue、Swift UI、Jetpack Composeがこの問題をネむティブに解決する方法を持っおいるこずを考えるず、特にむラむラしたす。

このスレッドで問題が䜕床も䜕床も明確に説明されおいるため、フラッタヌサンプルアプリの構築に時間を費やすべきではないず思うずいう点で、
たた、アプリを䜜成するには゜リュヌションが必芁なため、゜リュヌションを探しおいる堎合は、フラッタヌでアプリを䜜成するこずはできたせん。 この䌚話のフラッタヌの人々は少なくずもかなりはっきりしおいるので、圌らはフックが奜きではありたせん。 そしお、Flutterには、OPで説明されおいる問題に察する別の解決策がありたせん。 どのように曞くべきか。

これは少なくずも私には真剣に受け止められおいないず感じおいたす。@ Hixie 、申し蚳ありたせん。We understand the problem and want to solve itずいう意味で真剣に受け止められおいないずいうこずです。 他の宣蚀型フレヌムワヌクず同様に、明らかに実行されたようです。
別の、しかし同じ皮類の次のようなものに぀いお

曞くのは簡単ですか
開発者はフックの曞き方を孊ぶ必芁がありたすが、これは新しい抂念なので、ずおも難しいです

私を悲しくさせる。 なぜこれたでに䜕かを改善たたは倉曎するのですか 䜕があっおも、い぀でもその議論をするこずができたす。 たずえ新しい解決策が䞀床孊べばはるかに簡単で楜しいものであったずしおも。 そのステヌトメントのフックを倚くのものに眮き換えるこずができたす。 私の母は30幎前にマむクロ波に぀いおそのような文章を䜿うこずができたでしょう。 たずえば、文の「フック」を「フラッタヌ」たたは「ダヌツ」に眮き換えおも同じように機胜したす。

曞くのは簡単ですか
同じなので、曞くのも同じくらい簡単で、かなり簡単です。

@rrousselGitがis it easier to write? ブヌル回答の質問で意味するこずは、同じであれば答えはfalse / undefinedはないずいうこずではないず思いたす。

問題があるこずに同意すらしおいないので、どうやっおどこかに行くこずができるのかわかりたせん。倚くの人がこれを問題だず思っおいるだけです。 䟋えば

それは確かに人々が育おおきたものです。 それは私が内臓の経隓を持っおいるものではありたせん。 Flutterを䜿っお自分のアプリを曞くずきに問題だず感じたものではありたせん。 しかし、それは䞀郚の人々にずっおそれが本圓の問題ではないずいう意味ではありたせん。

そしお、倚くの人が䜕床も倚くの議論を提䟛しおきたしたが、なぜOPの゜リュヌションをコアにする必芁があるのか​​。
たずえば、サヌドパヌティが珟圚りィゞェットを䜿甚および䜜成するのず同じくらい簡単か぀自然に䜿甚できるようにするには、コアに含める必芁がありたす。 そしお、他の耇数の理由。 マントラは、パッケヌゞに入れるだけのようです。 しかし、フックの1぀ずしおすでにパッケヌゞがありたす。 それが解決されたのであれば、スレッドを閉じおみたせんか。

@rrousselGitを圌の申し出にかけおください。

ずにかく、ラむブで少し悲しいので、今は賌読を解陀しおいたす-どこにも行かないので、このスレッドをフォロヌしおください。 しかし、このスレッドが問題があるこずに同意する状態になり、OPの可胜な解決策に焊点を圓おるこずができるようになるこずを願っおいたす。 @Hixieがおそらく同意するように、人々が盎面しおいる問題を把握しおいない堎合、解決策を提案するのは少し無駄に思えるので、問題のある人々は

人々がそれを望んでいるにもかかわらず、フラッタヌはコアでこの問題を解決するべきではないずただはっきりず蚀うこずによっお、このスレッドを終了するこずであなたに幞運を祈っおいたす。 たたは解決策を芋぀けるこずによっお。 😘

LayoutBuilderは、ほずんどのビルダヌであるFWIWずは非垞に異なるりィゞェットです。 これたでに説明した提案はいずれも、LayoutBuilderのような問題には機胜したせん。たた、コメントの前に説明した芁件には、LayoutBuilderが含たれおいたせん。 この新機胜を䜿甚しおLayoutBuilderを凊理する必芁がある堎合は、知っおおくこずが重芁です。 @TimWhitingを䜿甚しお、提案のベヌスずなるサンプルアプリに、䟋ずしおレむアりトビルダヌが含たれおいるこずを確認するこずをお勧めしたす。

@Hixieはい、確かにいく぀かのサンプルが必芁です。 私は䜕かを準備したすしかし、サンプルが䞍完党である可胜性があるため、コンパむラの倉曎が必芁だず思いたす。 䞀般的な考え方は、ビルダヌをフラット化し、ビルダヌの実装方法を気にしないシンタックスシュガヌです。

それでも、Flutterチヌムの誰もSwiftUIを詳しく調べおいないずいう印象を受けおいたす。そうでなければ、私たちの懞念は理解しやすいず思いたす。 フレヌムワヌクの将来にずっお、他のプラットフォヌムから移行する人々ができるだけスムヌズに乗るこずが重芁であるため、他のプラットフォヌムに぀いおの十分な理解ず、賛吊䞡論の知識が必芁です。 そしお、Flutterの短所のいく぀かを修正できるかどうかを確認したす。 明らかに、FlutterはReactから倚くの優れたアむデアを取り入れおおり、新しいフレヌムワヌクでも同じこずができたす。

@ emanuel-lundman

これは少なくずも私には真剣に受け止められおいないず感じおいたす。@ Hixie 、申し蚳ありたせん。We understand the problem and want to solve itずいう意味で真剣に受け止められおいないずいうこずです。 他の宣蚀型フレヌムワヌクず同様に、明らかに実行されたようです。

私は問題を理解しおいないこずに完党に同意したす。 だから私はこの問題に取り組み続け、理解しようずしおいたす。 そのため、問題をカプセル化したデモアプリを䜜成するこずを提案したした。 最終的にフレヌムワヌクを根本的に倉曎するか、フレヌムワヌクに小さな機胜を远加するか、パッケヌゞによっお修正するかどうかは、実際には問題が䜕であるかによっお異なりたす。

@szotp

それでも、Flutterチヌムの誰もSwiftUIを詳しく調べおいないずいう印象を受けおいたす。そうでなければ、私たちの懞念は理解しやすいず思いたす。

私はSwiftUIを研究したした。 Swift UIコヌドを曞くこずは、Flutterコヌドよりも確かに冗長ではありたせんが、読みやすさのコストは非垞に高くなりたす。 倚くの「魔法」がありたす぀たり、コンシュヌマヌコヌドでは明らかではない方法で機胜するロゞック。 䞀郚の人が奜むスタむルだず完党に信じるこずができたすが、Flutterの匷みの1぀は、魔法がほずんどないこずでもあるず思いたす。 それはあなたが時々より倚くのコヌドを曞くこずを意味したすが、それはたたそのコヌドのデバッグが_はるかに_簡単であるこずを意味したす。

フレヌムワヌクにはたくさんのスタむルの䜙地があるず思いたす。 MVCスタむル、Reactスタむル、非垞に簡朔な魔法、魔法のない、しかし冗長な... Flutterのアヌキテクチャの利点の1぀は、移怍性の偎面がフレヌムワヌク自䜓から完党に分離されおいるため、すべおのツヌルを掻甚できるこずです。 -クロスプラットフォヌムのサポヌト、ホットリロヌドなど-しかし、たったく新しいフレヌムワヌクを䜜成したす。 flutter_spritesなどの他のFlutterフレヌムワヌクがすでにありたす。同様に、フレヌムワヌク自䜓は階局化された方法で蚭蚈されおいるため、たずえば、すべおのRenderObjectロゞックを再利甚できたすが、Widgetsレむダヌの代わりになりたす。りィゞェットが倚すぎるので、誰かがそれを眮き換える代替フレヌムワヌクを䜜成する可胜性がありたす。 そしおもちろん、パッケヌゞングシステムがあるので、既存のフレヌムワヌクコヌドを倱うこずなく機胜を远加できたす。

ずにかく、ここでの私の䜙談のポむントは、これがオヌルオアナッシングではないずいうこずです。 長期的には、あなたを幞せにする゜リュヌションを採甚するこずにならない堎合でも、それはあなたが奜きな補品の郚分から利益を享受し続けるこずができないずいう意味ではありたせん。


この問題に関心のある人は、 @ TimWhitingず様子を瀺すアプリを䜜成するこずをお勧めしたすhttps://github.com/TimWhiting/local_widget_state_approaches。 これは、ここでコメントしおいるすべおの人々フックが奜きな人ず嫌いな人を含むのニヌズに察応する方法でこの問題に察凊する方法の提案を䜜成するのに盎接圹立ちたす。

「_ビルダヌをフラット化し、ビルダヌの実装方法を気にしないシンタックスシュガヌ。_」がファヌストクラスの機胜ずしお開発者に望たれる理由を理解するのはそれほど難しいこずではありたせん。 代替アプロヌチの問題を䜕床も抂説しおきたした。

芁するに、ビルダヌは再利甚性の問題を解決したすが、読みやすく、構成するのは困難です。 「問題」は、非垞に読みやすいビルダヌのような機胜が必芁なこずです。

3぀のネストされたビルダヌが読みにくいこず、たたはビルダヌが䞀般にコヌドの再利甚の目的を実際に果たしおいないこずに基本的に同意しない堎合、アプリはそれをより明確に瀺すこずはできたせん。 私たちの倚くは実際にはネストを枛らすのが本圓に奜きで、アプリケヌション党䜓にコヌドを耇補するのは本圓に奜きではないので、2぀の非理想的なオプションの間に立ち埀生しおいるず聞いおさらに重芁です。

私は今週末、文字通り䜕時間も自分の時間を過ごしたした。それ以前のGoogleの時間は蚀うたでもなく、この問題を怜蚎し、考えられる解決策を説明し、解決しようずしおいるこずを正確に匕き出しようずしおいたす。

ありがたいです

䜕が問題なのか理解䞍足ず混同しないでください。

理解が足りなくおも倧䞈倫ですが、珟状は絶望的です。
議論の冒頭で指摘された点に぀いおは、ただ議論䞭です。

私の芳点からは、さたざたな問題を玹介する詳现なコメントを曞いたり、質問に答えたりするのに䜕時間も費やしたような気がしたすが、私のコメントは华䞋され、同じ質問が再床出されたした。

たずえば、珟圚の構文の可読性の欠劂が議論の䞭心にありたす。
これを裏付けるために、読みやすさの問題をいく぀か分析したした。

これらの分析にはかなりの数がありたす👍そしお他の人々は同意しおいるようです

それでも最近の回答によるず、読みやすさの問題はありたせん https 

あなたも提案したした

Widget build(context) {
  var result = Text('result:');
  var builder1 = (BuildContext context, AsyncSnapshot<int> snapshot) {
    return Row(children: [result, Text(snapshot.data)]);
  };
  result = StreamBuilder(stream: _stream1, builder: builder1);
  var builder2 = (BuildContext context, AsyncSnapshot<int> snapshot) {
    return Column(children: [result, Text(snapshot.data)]);
  };
  result = StreamBuilder(stream: _stream2, builder: builder2);
}

これが読めないこずを知っおいる

これらの2぀のコメントから、次のように結論付けるこずができたす。

  • 読みやすさの問題があるこずに同意したせん
  • 読みやすさがこの問題の範囲の䞀郚であるかどうかはただ䞍明です

フックの唯䞀の目的がビルダヌの構文を改善するこずであるこずを考えるず、これは聞いおがっかりしたす。ビルダヌは再利甚性のピヌクにありたすが、読みやすさや曞き蟌み性が劣っおいたす。
そのような基本的な事実に同意しないず、私たちに䜕ができるかわかりたせん。

@Hixieありがずう、これはあなたの芖点を理解するのに倧いに圹立ちたす。 私は圌らがコヌドマゞックで行き過ぎたかもしれないこずに同意したす、しかし私は圌らが正しかったこずは少なくずもいく぀かあるず確信しおいたす。

そしお、私はFlutterのレむダヌドアヌキテクチャがずおも奜きです。 りィゞェットも䜿い続けたいです。 したがっお、おそらく答えは、DartFlutterの拡匵性を改善するこずです。これは私にずっおは次のようになりたす。

コヌド生成をよりシヌムレスにしたす-DartでSwiftUIマゞックを実装するこずは可胜かもしれたせんが、必芁な通垞のセットアップは倧きすぎお遅すぎたす。

コヌド生成の䜿甚がパッケヌゞのむンポヌトずいく぀かの泚釈の平手打ちのように単玔である堎合、議論された問題を抱えおいる人々はそれを行うだけで文句を蚀うのをやめたす。 残りは、叀き良きStatefulWidgetsを盎接䜿甚し続けたす。

線集 flutter generateは良い方向ぞの䞀歩だったず思いたす、それが削陀されたこずを残念に思いたす。

これは、次のFlutter DeveloperSurveyで尋ねる非垞に興味深い質問になるず思いたす。

それは良いスタヌトになるでしょう。 この問題をさたざたな郚分/質問に分けお、これがFlutter開発者が解決したい本圓の問題であるかどうかを確認しおください。

それが明確になるず、この䌚話はより流暢で豊かになりたす

私の芳点からは、さたざたな問題を玹介する詳现なコメントを曞いたり、質問に答えたりするのに䜕時間も費やしたような気がしたすが、私のコメントは华䞋され、同じ質問が再床出されたした。

同じ質問をしおいるのは、答えがわからないからです。

たずえば、以前のコメントhttps://github.com/flutter/flutter/issues/51752#issuecomment-670959424に戻りたす。

議論されおいる問題は次のずおりです。

Widget build(context) {
  return ValueListenableBuilder<String>(
    valueListenable: someValueListenable,
    builder: (context, value, _) {
      return StreamBuilder<int>(
        stream: someStream,
        builder: (context, value2) {
          return TweenAnimationBuilder<double>(
            tween: Tween(...),
            builder: (context, value3) {
              return Text('$value $value2 $value3');
            },
          );
        },
      );
    },
  );
}

このコヌドは読み取り可胜ではありたせん。

私はそれに぀いお読めないものが本圓にわかりたせん。 それは䜕が起こっおいるのかを正確に説明しおいたす。 4぀のりィゞェットがありたす。3぀のりィゞェットにはビルダヌメ゜ッドがあり、1぀には文字列がありたす。 個人的には型を省略したせんが、倉数が䜕なのかわからないので読みづらくなるず思いたすが、倧きな問題ではありたせん。

なぜこれが読めないのですか

明確にするために、明らかにあなたはそれが読めないこずに気づきたす、私はあなたが間違っおいるず蚀っおいるのではありたせん。 理由がわかりたせん。

構文を次のように倉曎する新しいキヌワヌドを導入するこずで、読みやすさの問題を修正できたす。

Widget build(context) {
  final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);
  final value2 = keyword StreamBuilder(stream: someStream);
  final value3 = keyword TweenAnimationBuilder(tween: Tween(...));

  return Text('$value $value2 $value3');
}

このコヌドは非垞に読みやすく、フックずは無関係であり、制限の圱響を受けたせん。

確かに冗長ではありたせん。 少なくずも私にずっおは、これ以䞊読みやすいかどうかはわかりたせん。 より倚くの抂念がありたす珟圚、りィゞェットずこの「キヌワヌド」機胜の䞡方がありたす。 より倚くの抂念はより倚くの認知的負荷を意味したす。 これらのオブゞェクトがどれだけ独立しおいるかによっおは、効率が䜎䞋する可胜性もありたす。たずえば、アニメヌションが垞にリッスン可胜な倀ずストリヌムよりも頻繁に倉曎される堎合、通垞はトリガヌされないにもかかわらず、ValueListenableBuilderずStreamBuilderを再構築しおいたす。 ;たた、初期化ロゞックを入力しお、ビルドごずにスキップする必芁がありたす。

冗長性は問題ではないずおっしゃっおいたので、簡朔であるこずが読みやすい理由ではないず思いたすただし、問題のタむトルずに「冗長すぎる」ず入力したため、これに぀いおも混乱しおいたす。問題の元の説明。 むンデントを枛らしたいずおっしゃいたしたが、むンデントなしでビルダヌを䜿甚するバヌゞョンも刀読できないず説明したので、おそらく問題はオリゞナルのむンデントではありたせん。

ビルダヌは再利甚性のピヌクであり、別の構文が必芁だず蚀いたすが、提案した提案はビルダヌのようなものではないためりィゞェットや芁玠を䜜成したせん、特にビルダヌの偎面ではありたせん。探しおいる。

あなたはあなたが奜きな解決策フックを持っおいたす、それは私が知る限りうたくいきたす、しかしあなたは人々がフックを䜿うようにフレヌムワヌクで䜕かを倉えたいですか 私も理解しおいたせん。なぜなら、人々がフックをパッケヌゞずしお䜿甚するのに十分なほど奜きではない堎合、それはおそらくフレヌムワヌクにずっおも良い解決策ではないからです䞀般的に、私たちはパッケヌゞ、さらには機胜を䜿甚する方向に進んでいたすFlutterチヌムは、その䟡倀のために䜜成したす。

コヌドをより簡単に再利甚したいずいう芁望があるこずを理解しおいたす。 それが䜕を意味するのかわかりたせん。

以䞋は、読みやすさにおいお䞊蚘の2぀のバヌゞョンずどのように比范されたすか

Widget build(context) {
  return
    ValueListenableBuilder(valueListenable: someValueListenable, builder: (context, value, _) =>
    StreamBuilder(stream: someStream, builder: (context, value2) =>
    TweenAnimationBuilder(tween: Tween(...), builder: (context, value3) =>
    Text('$value $value2 $value3'),
  )));
}

@szotp珟圚のcodegen゜リュヌションにあたりにも倚くの摩擊がある堎合は、そこで改善を求めるバグを提出するこずを躊躇しないでください。

@jamesblasco人々が解決したい本圓の問題がここにあるこずに疑いの䜙地はないず思いたす。 私にずっおの問題は、たさにその問題が䜕であるかずいうこずです。そうすれば、解決策を蚭蚈するこずができたす。

フックの欠陥やコヌドに含めたいずいう懞念に答えるこずはできたしたが、今はそれを重芖すべきではないず思いたす。

たず、問題が䜕であるかに぀いお合意する必芁がありたす。 そうしないず、他のトピックに぀いおどのように合意できるかわかりたせん。

私はそれに぀いお読めないものが本圓にわかりたせん。 それは䜕が起こっおいるのかを正確に説明しおいたす。 4぀のりィゞェットがありたす。3぀のりィゞェットにはビルダヌメ゜ッドがあり、1぀には文字列がありたす。 個人的には型を省略したせんが、倉数が䜕なのかわからないので読みづらくなるず思いたすが、倧きな問題ではありたせん。

ここでの問題の倧郚分は、コヌディングの方法がほずんどの人のコヌディング方法ず倧幅に異なるこずだず思いたす。

たずえば、Flutterずあなたが䞡方を䞎えたアプリの䟋

  • dartfmtを䜿甚しないでください
  • always_specify_typesを䜿甚する

これらの2぀のポむントだけで、それがコミュニティの1以䞊を占めるずしたら、私は驚きたす。

そのため、読み取り可胜ず評䟡するものは、ほずんどの人が読み取り可胜ず考えるものずは倧きく異なる可胜性がありたす。

私はそれに぀いお読めないものが本圓にわかりたせん。 それは䜕が起こっおいるのかを正確に説明しおいたす。 4぀のりィゞェットがありたす。3぀のりィゞェットにはビルダヌメ゜ッドがあり、1぀には文字列がありたす。 個人的には型を省略したせんが、倉数が䜕なのかわからないので読みづらくなるず思いたすが、倧きな問題ではありたせん。

なぜこれが読めないのですか

私の掚奚は、特定のものを怜玢するずきにあなたの目がどこを芋おいるか、そしおそこに到達するために䜕ステップかかるかを分析するこずです。

実隓しおみたしょう
2぀のりィゞェットツリヌを提䟛したす。 1぀は線圢構文を䜿甚し、もう1぀はネストされた構文を䜿甚したす。
たた、そのスニペットで探す必芁のある具䜓的な事項に぀いおも説明したす。

線圢構文たたはネストされた構文を䜿甚するこずに察する答えを芋぀けるのは簡単ですか

質問

  • このビルドメ゜ッドによっお返される非ビルダヌりィゞェットは䜕ですか
  • 誰が倉数barを䜜成したすか
  • ビルダヌはいく぀ありたすか

ビルダヌの䜿甚

りィゞェットビルドコンテキスト{
 ValueListenableBuilderを返したす
 valueListenablesomeValueListenable、
 ビルダヌcontext、foo、_{
 StreamBuilderを返す
 ストリヌムsomeStream、
 ビルダヌ:(コンテキスト、baz{
 TweenAnimationBuilderを返す
 トゥむヌントゥむヌン...、
 ビルダヌ:(コンテキスト、バヌ{
 Container;を返したす。
 }、
 ;
 }、
 ;
 }、
 ;
 }

線圢構文の䜿甚

りィゞェットビルドコンテキスト{
 最終的なfoo =キヌワヌドValueListenableBuildervalueListenablesomeValueListenable;
 最終バヌ=キヌワヌドStreamBuilderstreamsomeStream;
 最終的なbaz =キヌワヌドTweenAnimationBuildertweenTween...;

Image;を返す }


私の堎合、ネストされたコヌドを調べお答えを芋぀けるのに苊劎しおいたす。
䞀方、線圢ツリヌで答えを芋぀けるのは瞬時です

むンデントを枛らしたいずおっしゃいたしたが、むンデントなしでビルダヌを䜿甚するバヌゞョンも刀読できないず説明したので、おそらく、問題はオリゞナルのむンデントではありたせん。

StreamBuilderを耇数の倉数に分割するこずは深刻な提案でしたか
私の理解では、これは議論をするための皮肉な提案でした。 そうじゃなかった このパタヌンは、倧きなりィゞェットであっおも、より読みやすいコヌドに぀ながるず本圓に思いたすか

䟋が機胜しないずいう事実を無芖しお、なぜそれが読めないのかを説明するためにそれを分解しおもかたいたせん。 それは䟡倀がありたすか

`` `ダヌツ
りィゞェットビルドコンテキスト{
戻る
ValueListenableBuildervalueListenablesomeValueListenable、buildercontext、value、_=>
StreamBuilderstreamsomeStream、buildercontext、value2=>
TweenAnimationBuildertweenTween...、ビルダヌcontext、value3=>
Text '$ value $ value2 $ value3'、
;
}

それは良く芋えたす。
しかし、それは人々がdartfmtを䜿甚しないこずを前提ずしおいたす

dartfmtを䜿甚するず、次のこずができたす。

Widget build(context) {
  return ValueListenableBuilder(
      valueListenable: someValueListenable,
      builder: (context, value, _) => StreamBuilder(
          stream: someStream,
          builder: (context, value2) => TweenAnimationBuilder(
                tween: Tween(),
                builder: (context, value3) => Text('$value $value2 $value3'),
              )));
}

これは元のコヌドずほずんど倉わりたせん。

ビルダヌは再利甚性のピヌクであり、別の構文が必芁だず蚀いたすが、提案した提案はビルダヌのようなものではないためりィゞェットや芁玠を䜜成したせん、特にビルダヌの偎面ではありたせん。探しおいる。

これが実装の詳现です。
芁玠があるかどうかに特別な理由はありたせん。
実際、芁玠があるず面癜いかもしれたせん。そうすれば、 LayoutBuilderず、堎合によっおはGestureDetector含めるこずができたす。

優先床は䜎いず思いたす。 しかし、Reactコミュニティでは、さたざたなフックラむブラリの䞭で、次のこずを確認したした。

  • useIsHovered –りィゞェットがホバヌされおいるかどうかを瀺すブヌル倀を返したす
  • useSize –おそらくFlutterのuseContraintsである必芁がありたす関連するUIのサむズを瀺したす。

これらのオブゞェクトがどれだけ独立しおいるかによっおは、効率が䜎䞋する可胜性もありたす。たずえば、アニメヌションが垞にリッスン可胜な倀ずストリヌムよりも頻繁に倉曎される堎合、通垞はトリガヌされないにもかかわらず、ValueListenableBuilderずStreamBuilderを再構築しおいたす。 ;たた、初期化ロゞックを入力しお、ビルドごずにスキップする必芁がありたす。

それは、゜リュヌションがどのように解決されるかによっお異なりたす。

蚀語の修正を行う堎合、この問題はたったく問題になりたせん。

私たちはそれを䜜るこずができたす

Widget build(context) {
  final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);
  final value2 = keyword StreamBuilder(stream: someStream);
  final value3 = keyword TweenAnimationBuilder(tween: Tween(...));

  return Text('$value $value2 $value3');
}

「コンパむル」しお

Widget build(context) {
  return ValueListenableBuilder<String>(
    valueListenable: someValueListenable,
    builder: (context, value, _) {
      return StreamBuilder<int>(
        stream: someStream,
        builder: (context, value2) {
          return TweenAnimationBuilder<double>(
            tween: Tween(...),
            builder: (context, value3) {
              return Text('$value $value2 $value3');
            },
          );
        },
      );
    },
  );
}

フックを䜿甚しおいる堎合、flutter_hooksにはHookBuilderりィゞェットが付属しおいるため、必芁なずきに分割するこずができたす。
同様に、特にここで䜜成した䟋では、それが本圓に問題であるかどうかを刀断するための適切なベンチマヌクが必芁になりたす。

フックを䜿甚しお、1぀の芁玠のみを再構築しおいたす。
Builderを䜿甚するず、再構築は耇数の芁玠に分割されたす。 それは、たずえ小さくおも、いくらかのオヌバヌヘッドも远加したす。

すべおのフックを再評䟡する方が速いこずは䞍可胜ではありたせん。 これが、フックを蚭蚈するずきに圌らが思い぀いたReactチヌムの結論だったようです。
ただし、これはFlutterには圓おはたらない堎合がありたす。

なぜこれが読めないのですか

ネスティングがあるため、ネスティングを䜿甚するず、無芖できる郚分ず、䜕が起こっおいるのかを理解するために䞍可欠な郚分をすばやくスキャンしお知るこずが難しくなりたす。 コヌドは本質的に「シヌケンシャル」ですが、ネストはこれを隠したす。 ネストはたた、それを操䜜するのを難しくしたす-2぀のものを䞊べ替えたいず想像しおください-たたは2぀の間に新しいものを泚入したす-真のシヌケンシャルコヌドでは簡単ですが、ネストを操䜜する必芁がある堎合は困難です。

これはasync / awaitsugarず生のFutureAPIでの䜜業に非垞に䌌おおり、その䞋に継続ベヌスの抂念がありたすそしお賛成ず反察の議論も非垞に䌌おいたす-はいFuture APIは盎接䜿甚でき、䜕も隠したせんが、読みやすさず保守性確かに良くありたせん-async / awaitが勝者です。

私の掚奚は、特定のものを怜玢するずきにあなたの目がどこを芋おいるか、そしおそこに到達するために䜕ステップかかるかを分析するこずです。

私は25幎間、10以䞊の異なる蚀語でプログラミングを行っおきたしたが、それはコヌドを読みやすくするものを評䟡するためのより悪い方法です。 ゜ヌスコヌドの読みやすさは泚意が必芁ですが、「私の目がどこを芋おいるか」や䜿甚するコヌドの行数ではなく、プログラミングの抂念ずロゞックをどれだけうたく衚珟するかが重芁です。

むしろ、皆さんは読みやすさに重点を眮きすぎお、保守性に重点を眮いおいないようです。

コヌドの__intent__がわかりにくく、同じ堎所にさたざたな懞念事項が隠されおいるず、保守が難しくなるため、䟋は読みにくくなりたす。


final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);

䟡倀は䜕でさえありたすか りィゞェット 文字列倉数 私はそれが内郚で䜿甚されおいるこずを意味したす
return Text('$value $value2 $value3');

基本的に必芁なのは、りィゞェットBのbuildメ゜ッドで倉数Aを参照するこずにより、Aの倀が倉曎されるたびにBを再構築する必芁があるずいうこずです。 それは文字通りmobxが行うこずであり、適切な量の魔法/ボむラヌプレヌトで正確に行いたす。


final value2 = keyword StreamBuilder(stream: someStream);

これは䜕を返す必芁がありたすか りィゞェット ストリヌム 文字列倀

繰り返したすが、文字列倀のように芋えたす。 したがっお、buildメ゜ッドでストリヌムを単玔に参照し、ストリヌムが倀を発行するたびにそのりィゞェットを再構築し、発行された倀にアクセスできるようにし、りィゞェットが䜜成/曎新されるたびにストリヌムを䜜成/曎新/砎棄できるようにする必芁がありたす。 /砎壊されたした 1行のコヌドで ビルドメ゜ッドの内郚

はい、mobxを䜿甚するず、ビルドメ゜ッドを「より読みやすい」䟋ずたったく同じように芋せるこずができたすオブザヌバブルを参照する堎合を陀く。 フックの堎合ず同じように、すべおの䜜業を実行する実際のコヌドを䜜成する必芁がありたす。 実際のコヌドは玄10行で、どのりィゞェットでも再利甚できたす。


final value3 = keyword TweenAnimationBuilder(tween: Tween(...));

文字列を返す「TweenAnimationBuilder」ずいうクラス なぜこれがひどい考えなのか、私は近づいおいたせん。

以䞋の間でむンデント/読みやすさに違いはありたせん。

Future<double> future;

AsyncSnapshot<double> value = keyword FutureBuilder<double>(future: future);

ず

Future<double> future;

double value = await future;

どちらもたったく同じこずを行いたす。オブゞェクトをリッスンし、その倀をアンラップしたす。

私はそれに぀いお読めないものが本圓にわかりたせん。 それは䜕が起こっおいるのかを正確に説明しおいたす。 4぀のりィゞェットがありたす。3぀のりィゞェットにはビルダヌメ゜ッドがあり、1぀には文字列がありたす。 個人的には型を省略したせんが、倉数が䜕なのかわからないので読みづらくなるず思いたすが、倧きな問題ではありたせん。

同じ議論がPromise / Futureチェヌンにも圓おはたりたす。

foo().then(x =>
  bar(x).then(y =>
    baz(y).then(z =>
      qux(z)
    )
  )
)

vs

let x = await foo();
let y = await bar(x);
let z = await baz(y);
await qux(z);

最初の曞き方では、Promiseが内郚で䜜成されおいるこず、およびチェヌンがどのように正確に圢成されおいるかが明確になっおいるず蚀えたす。 あなたがそれを賌読しおいるのか、それずもPromisesが構文に倀するずいう点でBuildersずは根本的に異なるず考えおいるのだろうか。

文字列を返す「TweenAnimationBuilder」ずいうクラス なぜこれがひどい考えなのか、私は近づいおいたせん。

Promises / Futuresに぀いおも同じ議論をするこずができ、 awaitはPromiseを返すずいう事実を芆い隠しおいるず蚀うこずができたす。

構文を介しお物事を「アンラップ」するずいう考えは、ほずんど新しいものではないこずに泚意する必芁がありたす。 はい、䞻流の蚀語ではasync / awaitを介しお提䟛されおいたしたが、たずえば、Fには、䞀郚のハヌドコアFP蚀語のdo衚蚘に䌌た蚈算匏がありたす。 そこでは、それははるかに匷力であり、特定の法則を満たす任意のラッパヌで動䜜するように䞀般化されおいたす。 モナドをダヌトに远加するこずを提案しおいるわけではありたせんが、非同期呌び出しに必ずしも察応しないものを「アンラップ」するためのタむプセヌフな構文の前䟋があるこずは間違いなくあるず思いたす。

䞀歩埌退しお、ここの倚くの人々が私自身も含めお苊劎しおいるこずの1぀は、読みやすさに぀いおのこの質問だず思いたす。 @rrousselGitが述べたように、珟圚のBuilderベヌスのアプロヌチでは、この可読性の問題のスレッド党䜓に倚くの䟋がありたす。 私たちの倚くにずっお、これは自明のようです。

Widget build(context) {
  return ValueListenableBuilder<String>(
    valueListenable: someValueListenable,
    builder: (context, value, _) {
      return StreamBuilder<int>(
        stream: someStream,
        builder: (context, value2) {
          return TweenAnimationBuilder<double>(
            tween: Tween(...),
            builder: (context, value3) {
              return Text('$value $value2 $value3');
            },
          );
        },
      );
    },
  );
}

これよりも倧幅に読みにくくなりたす。

Widget build(context) {
  final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);
  final value2 = keyword StreamBuilder(stream: someStream);
  final value3 = keyword TweenAnimationBuilder(tween: Tween(...));

  return Text('$value $value2 $value3');
}

しかし、 @ Hixieず@Rudikszは、2番目の方が最初の方より読みやすいずいう考えに玍埗しおいないたたは積極的に反察しおいるため、明らかに自明ではありたせん。

したがっお、2番目のコヌドブロックが最初のコヌドブロックよりも読みやすい理由に぀いおの私の内蚳は次のずおりです少しでも䟡倀がありたす。

1.最初のコヌドボックは2番目のコヌドボックよりも倧幅にむンデントされおいたす

私の経隓では、むンデントは通垞、非同期性、分岐、たたはコヌルバックず同等であり、これらはすべお、むンデントされおいない線圢コヌドよりも倚くの認知的負荷を必芁ずしたす。 最初のコヌドブロックにはいく぀かのむンデントの局があり、そのため、ここで䜕が起こっおいるのか、そしお最終的に䜕がレンダリングされおいるのか単䞀のText を凊理するのに取るに足らない時間がかかりたす。 たぶん、他の人々は圌らの心の䞭でそのくがみを通しお働くのが䞊手です。


2番目のコヌドブロックには、問題を軜枛するむンデントはありたせん。

2.最初のコヌドブロックは、その意図を衚珟するためにより倚くの構文を必芁ずしたす

最初のコヌドブロックには、3぀のreturnステヌトメント、3぀のビルダヌステヌトメント、3぀のラムダヘッダヌ、3぀のコンテキスト、そしお最埌に3぀の倀がありたす。 最終的に私たちが気にするのは、これら3぀の䟡倀芳です。残りは、私たちをそこに導くための定型文です。 私は実際、これがこのコヌドブロックの最も難しい郚分であるず感じおいたす。 非垞に倚くのこずが起こっおおり、私が実際に気にかけおいる郚分ビルダヌから返される倀は非垞に小さいので、実際に必芁な郚分に集䞭するのではなく、粟神的な゚ネルギヌのほずんどをボむラヌプレヌトに費やしおいたす繰り返したすが、倀。


2番目のコヌドブロックでは、ボむラヌプレヌトが倧幅に削枛されおいるため、関心のある郚分に焊点を圓おるこずができたす。これも倀です。

3.最初のコヌドブロックは、ネストの最深郚にあるbuildメ゜ッドの最も重芁な郚分を非衚瀺にしたす。

このbuildメ゜ッドのすべおの郚分が重芁であるこずを認識しおいたすが、このスタむルの宣蚀型UIコヌドを読んでいるずきに、私が通垞探しおいるのは、衚瀺されるものすべおです。ナヌザヌ。この堎合は、最も深いネストされたビルダヌに埋め蟌たれたTextりィゞェットです。 そのTextりィゞェットは、前面ず䞭倮に配眮されるのではなく、むンデント、構文、および意図の耇数のレむダヌに埋め蟌たれおいたす。 これらのレむダヌの1぀にColumnたたはRowをスロヌするず、さらに深くネストされ、その時点では、最もむンデントされたセクションたでトレヌスするだけのメリットはありたせん。 。


2番目のコヌドブロックでは、返される実際のレンダリング可胜なWidgetは関数の䞋郚にあり、これはすぐにわかりたす。 さらに、OPが提案する構文のようなものがある堎合、芖芚的なWidget垞に関数の䞋郚にあるこずを期埅できるため、コヌドがはるかに予枬可胜で読みやすくなりたす。

ネスティングに関しおは、_tree_を衚珟するネスティングず_sequence_を衚珟するネスティングには違いがありたす。

通垞のView -> Textネスティングなどの堎合、ネスティングは画面䞊の芪子関係を衚すため、重芁です。 コンテキストFlutterにあるかどうかはわかりたせんなどの機胜の堎合、コンテキストのスコヌプを衚したす。 したがっお、ネスト自䜓はそのような堎合に重芁な意味的意味を持ち、無芖するこずはできたせん。 芪ず子の堎所を入れ替えお、結果が同じになるず期埅するこずはできたせん。

ただし、ビルダヌのネストReactでは「レンダリングプロップ」ずも呌ばれたすたたはPromisesのネストでは、ネストは䞀連の倉換/拡匵を䌝達ABuilder -> BBuilder -> CBuilderネストする堎合、それらの芪子関係は远加の意味を䌝えたせん。

以䞋のスコヌプで3぀の倀すべおが䜿甚可胜である限り、それらのツリヌ構造は実際には関係ありたせん。 これは抂念的に「フラット」であり、ネストは構文のアヌティファクトにすぎたせん。 もちろん、それらは互いの倀を䜿甚する堎合がありたすこの堎合、順序が重芁ですが、これはシヌケンシャル関数呌び出しの堎合にも圓おはたり、ネストせずに実行できたす。

これがasync/awaitが魅力的な理由です。 䜎レベルのメカニズムを説明する远加情報Promisesの芪子関係を削陀し、代わりに高レベルのむンテントシヌケンスを説明するに集䞭できるようにしたす。

ツリヌはリストよりも柔軟な構造です。 しかし、各芪に子が1぀しかない堎合、それは病理孊的ツリヌ、

以前に「これは定型文ではない」ず蚀ったので、これは実際には興味深いものですが、今では自分自身ず矛盟しおいるように芋えたす。 ここには2぀のこずがあるず思いたす。

ビルダヌたたは少なくずもReactのレンダリングプロップは、それ自䜓が「再利甚可胜なロゞック」問題の解決策AFAIKです。 それらをたくさん䜿甚するず、人間工孊的ではないずいうだけです。 むンデントによっお、同じコンポヌネントで4぀たたは5぀以䞊を䜿甚するこずは圓然お勧めできたせん。 次の各レベルは読みやすさのヒットです。

したがっお、私には解決されおいないように思われる郚分は、ネストのリヌダヌコストを削枛するこずです。 そしお、その匕数はasync / await堎合ずたったく同じ匕数です。

次の理由により、読みにくくなっおいたす。

  • 空癜の過床の䜿甚はうたくスケヌリングしたせん。 モニタヌには非垞に倚くの行しかありたせん。スクロヌルを匷制するず、読みやすさが䜎䞋し、集䞭的な負荷が増加したす。 すでに60行のりィゞェットツリヌがあり、ビルダヌのためにさらに15行を匷制したず想像しおください。理想的ではありたせん。
  • これはHzスペヌスを浪費したすが、これは䜙分なラッピングに぀ながるこずに制限されおおり、ラむンスペヌスをさらに浪費したす。
  • それは、葉のノヌド、別名コンテンツを巊偎からさらに抌し蟌み、䞀目で芋぀けるのが難しいツリヌに抌し蟌みたす。
  • 「䞻芁なプレヌダヌ」たたは「非定型文」を䞀目で識別するこずは非垞に困難です。 私の掚論が始たる前に、私は「重芁なものを芋぀ける」必芁がありたす。

これを確認するもう1぀の方法は、ボむラヌプレヌト以倖のコヌドを匷調衚瀺するこずです。これは、目で簡単に楜しむためにグルヌプ化されおいるのか、目でスキャンする必芁があるためにどこにでも散らばっおいるのかを瀺したす。

匷調衚瀺するず、これは非垞に簡単に掚論できたす。 それがないず、誰が䜕をどこで䜿甚しおいるかを把握する前に、冗長性のチャンク党䜓を読み取る必芁がありたす。
image

これず比范するず、匷調衚瀺は基本的に冗長です。私の目が他に行く堎所がないためです。
image

おそらく、読みやすさず可読性に䞍䞀臎があるこずは泚目に倀したす。 @Hixieは、モノリシッククラスファむルに時間を費やしおいる可胜性がありたす。そこでは、倧芏暡なツリヌを垞に読んで理解する必芁がありたすが、通垞のアプリ開発者は、䜕癟もの小さなクラスを構築するこずに

参考たでに、ReactのContextに盞圓するものは、攟棄されたりィゞェット/プロバむダヌです。

それらの唯䞀の違いは、フックの前に反応する堎合、Builderパタヌンを䜿甚しおコンテキスト/継承りィゞェットを䜿甚する必芁があったこずです。

䞀方、Flutterには、単玔な関数呌び出しで再構築をバむンドする方法がありたす。
したがっお、AttachedWidgetsを䜿甚しおツリヌをフラット化するためのフックは必芁ありたせん。これはBuilderの問題を回避する皮類です。

ビルダヌが必芁になる頻床が少ないため、これがおそらく議論が難しい理由の1぀です。

しかし、フックのような゜リュヌションを導入するず、 https//github.com/flutter/flutter/issues/30062の䞡方が解決されるこずに蚀及する䟡倀があり
およびhttps://github.com/flutter/flutter/issues/12992

たた、Flutterは基本的にすべおツリヌであり、私の意芋では他の蚀語よりもはるかに倚いため、 @ Hixieは深いネストされたツリヌの読み取りに慣れおいるようです。 もちろん、Flutter自䜓の䞻芁な開発者の1人ずしお、圌はそれに぀いおはるかに倚くの経隓を持っおいるでしょう。 Flutterは基本的に、 @ HixieがHTML5仕様を䜜成した経隓があるず思う、HTMLのように、深いネストを備えた巊から右のフレヌムワヌクず考えるこずができたす。 ぀たり、コヌドブロックの右端のポむントは、メむンロゞックず戻り倀が存圚する堎所です。

しかし、ほずんどの開発者はそうではありたせん、たたはロゞックは再び、むしろ、ネストされた暹朚に比べお、䞊から䞋に読んで、ここで、䞋の蚀語䞊から来たす。 これは、コヌドブロックの最䞋郚にありたす。 したがっお、圌が読めるものは、他の倚くの開発者にずっお必ずしもそうではありたせん。そのため、ここで読みやすさに関する意芋の二分法が芋られる可胜性がありたす。

それを芋る別の方法は、私の脳が芖芚的に線集するために必芁なコヌドの量です。 私にずっお、これは、ツリヌから返されるものを解析する前に、脳が実行しなければならない「うなり声」を正確に衚しおいたす。
image

簡単に蚀えば、ビルダヌバヌゞョンは、文字通り远加の情報やコンテキストを远加せずに、垂盎方向のフットプリントが4倍高く、コヌドをはるかにたばらな/分散した方法でパックしたす。 私の考えでは、それはオヌプンずシャットのケヌスであり、その理由だけで客芳的に読みにくく、むンデントの呚りの远加の認知的負荷や、私たち党員がフラッタヌで扱っおきた䞭括匧を䞊べるこずさえ考慮しおいたせん。

私の目を空腹のCPUず考えおください。これは、凊理甚にさらに最適化されおいたすか :)

通垞のView -> Textネスティングなどの堎合、ネスティングは画面䞊の_芪子関係_を衚すため重芁です。 コンテキストFlutterにあるかどうかはわかりたせんなどの機胜の堎合、コンテキストのスコヌプを衚したす。 したがっお、ネスト自䜓はそのような堎合に重芁な意味的意味を持ち、無芖するこずはできたせん。 芪ず子の堎所を入れ替えお、結果が同じになるず期埅するこずはできたせん。

完党に同意し、私はこれに぀いお先に述べたした。 状態を持぀远加の非ビゞュアルコントロヌラヌを䜿甚しおいるため、ビゞュアル衚瀺ツリヌに远加のコンテキストレむダヌを䜜成するこずは意味がありたせん。 5぀のアニメヌタヌを䜿甚しお、りィゞェットの深さは5局になりたしたか その高いレベルだけでも、珟圚のアプロヌチはちょっず臭いがしたす。

ここで私に飛び出す2぀の問題がありたす。

  1. 高䟡なリ゜ヌスを䜿甚する堎合、それがどれほど難しい/明瀺的であるかに぀いお、いく぀かの意芋の盞違があるのではないかず思いたす。 Flutterの哲孊は、開発者がそれらをい぀どのように䜿甚するかを真剣に考えるように、より困難/明瀺的にする必芁があるずいうものです。 ストリヌム、アニメヌション、レむアりトビルダヌなどは、簡単すぎるず非効率的に䜿甚される可胜性のある重芁なコストを衚しおいたす。

  2. ビルドは同期ですが、アプリ開発者ずしお扱う最も興味深いものは非同期です。 もちろん、ビルドを非同期にするこずはできたせん。 Stream / Animation / FutureBuilderのようなこれらの䟿利な機胜を䜜成したしたが、開発者が必芁ずするものに察しお垞に十分に機胜するずは限りたせん。 おそらく、フレヌムワヌクでStreamやFutureBuilderをあたり䜿甚しおいないこずを瀺しおいたす。

もちろん、非同期操䜜を操䜜するずきは、垞にカスタムレンダリングオブゞェクトを䜜成するように開発者に指瀺するのが解決策ではないず思いたす。 しかし、このバグで私が芋おいる䟋では、非同期ず同期の䜜業が混圚しおいるため、埅ちきれたせん。 ビルドは、すべおの呌び出しで䜕かを生成する必芁がありたす。

fwiw、Reactチヌムは、読みやすさの問題を1぀の動機ずしお再利甚するこずに取り組みたした。
フックの動機コンポヌネント間でステヌトフルロゞックを再利甚するのは難しい
Reactは、再利甚可胜な動䜜をコンポヌネントに「アタッチ」する方法を提䟛しおいたせん...これを解決しようずするパタヌンに粟通しおいるかもしれたせん...。 ただし、これらのパタヌンでは、コンポヌネントを䜿甚するずきにコンポヌネントを再構築する必芁がありたす。これは、煩雑で、コヌドを远跡するのが難しくなる可胜性がありたす。

これは、Flutterが珟圚ネむティブに「状態を構成する」方法を提䟛しおいない方法ず非垞によく䌌おいたす。 たた、私たちビルダヌがレむアりトツリヌを倉曎し、操䜜がより面倒になり、「埓うのが難しくなる」ず、゚コヌが発生したす。

@dnfield build毎回呌び出す必芁がある堎合は、フックをbuildメ゜ッドに含たないようにしお、ビルドが垞に同期されるようにするこずができたす。぀たり、 initStateクラス内にフックを配眮したす。 disposeはです。 フックを曞く人から、そうするこずに問題はありたすか

Promises / Futuresに぀いおも同じ議論をするこずができ、 awaitはPromiseを返すずいう事実を芆い隠しおいるず蚀うこずができたす。

いいえ、したせん。 Awaitは、文字通り1぀の機胜の単なる構文糖衣です。 冗長なFuturesたたは宣蚀型構文を䜿甚する堎合、コヌドの__intent__は同じです。

ここでの芁求は、たったく異なる懞念に察凊する゜ヌスコヌドを同じ傘の䞋に移動し、あらゆる皮類の異なる動䜜を1぀のキヌワヌドの背埌に隠し、䜕らかの圢で認知的負荷を軜枛するず䞻匵するこずです。

これは完党に誀りです。そのキヌワヌドを䜿甚するたびに、結果が非​​同期操䜜を実行したり、䞍芁な再構築をトリガヌしたり、長期間有効なオブゞェクトを初期化したり、ネットワヌク呌び出しを行ったり、ディスクからファむルを読み取ったり、静的な倀を返したりするのかどうか疑問に思う必芁がありたす。 。 これらはすべお非垞に異なる状況であり、䜿甚しおいるフックのフレヌバヌに粟通しおいる必芁がありたす。

ここでのほずんどの開発者は、実装の詳现を気にせずにこれらの「フック」を䜿甚できるため、このような詳现に煩わされるこずを嫌い、簡単な開発を望んでいるこずを議論から理解しおいたす。
このいわゆる「フック」を完党な意味を理解せずに意地悪に䜿甚するず、非効率的で悪いコヌドに぀ながり、人々が自分の足を撃ち殺す原因になりたす。したがっお、「初心者開発者の保護」の問題さえ解決したせん。

ナヌスケヌスが単玔な堎合は、そうです、フックを気たたに䜿甚できたす。 ビルダヌは奜きなだけ䜿甚しおネストできたすが、アプリが耇雑になり、コヌドの再利甚が困難になるため、独自のコヌドずアヌキテクチャにもっず泚意を払う必芁があるず思いたす。 朜圚的に数癟䞇人のナヌザヌ向けのアプリを䜜成しおいる堎合、重芁な詳现を抜象化する「魔法」を䜿甚するこずを非垞に躊躇したす。 今のずころ、FlutterのAPIは非垞に単玔なナヌスケヌスには単玔であり、誰でも非垞に効率的な方法であらゆる皮類の耇雑なロゞックを実装できる柔軟性を備えおいたす。

@Rudiksz繰り返したすが、誰もあなたにフックぞの移動を匷制しおいたせん。 珟圚のスタむルは匕き続き存圚したす。 この知識に盎面しおあなたの議論は䜕ですか

ずにかく、耇数のフックが䜕らかの圢でアプリをブロックしおいるこずを確認した埌でも、効率的なコヌドを蚘述できたす。 珟圚のスタむルの堎合ず同じように、プロファむリングしたり、アプリを実行したりするず衚瀺されたす。

@Rudiksz繰り返したすが、誰もあなたにフックぞの移動を匷制しおいたせん。 珟圚のスタむルは匕き続き存圚したす。 この知識に盎面しおあなたの議論は䜕ですか

ああ、この同じ議論は、フレヌムワヌクの問題に぀いお䞍平を蚀っおいる人々にも圓おはたりたす。 フックパッケヌゞを䜿甚しないように匷制しおいる人は誰もいたせん。

私はここで非垞に鈍くなりたす。
この問題は、フック、ステヌトフルりィゞェット、および誰が䜕を䜿甚するかに関するものではなく、5行少ないコヌドを蚘述できるようにするために数十幎のベストプラクティスを元に戻すこずに関するものです。

あなたの議論は実際には機胜したせん。 この問題が発生した理由は、珟圚のモデルがすでにフレヌムワヌクにネむティブに存圚しおいるため、flutter_hooksパッケヌゞがフレヌムワヌクに䜕かを含めるこずで可胜なすべおのこずを実行しないためです。 議論は、flutter_hooksの機胜をフレヌムワヌクにネむティブに移動するこずです。 あなたの議論は、私が珟圚のモデルでできるこずは䜕でも、フックパッケヌゞでもできるず仮定しおいたすが、これは真実ではありたせん。この議論の他の人からのようです。 それらが真である堎合、それは機胜したす。これは、フックがネむティブにフレヌムワヌクにあるこずも意味したす。したがっお、フックず非フックは同等であるため、フックベヌスず同様に珟圚のモデルを䜿甚できたす。モデル、それは私が䞻匵しおいたものです。

コヌドを読みやすくするこずがベストプラクティスであり、過床のネストはアンチパタヌンであるこずがわかっおいるため、ベストプラクティスがどこから来おいるのかわかりたせん。 どのベストプラクティスを正確に参照しおいたすか

fwiw、Reactチヌムは、読みやすさの問題を1぀の動機ずしお再利甚するこずに取り組みたした。
フックの動機コンポヌネント間でステヌトフルロゞックを再利甚するのは難しい
Reactは、再利甚可胜な動䜜をコンポヌネントに「アタッチ」する方法を提䟛しおいたせん...これを解決しようずするパタヌンに粟通しおいるかもしれたせん...。 ただし、これらのパタヌンでは、コンポヌネントを䜿甚するずきにコンポヌネントを再構築する必芁がありたす。これは、煩雑で、コヌドを远跡するのが難しくなる可胜性がありたす。

FlutterがReactよりもはるかに玠晎らしいこずに぀いおみんなが絶賛しおいるのを聞いおいたす。 たぶんそれはReactのようにすべおを行うわけではないからですか 䞡方の方法を䜿甚するこずはできたせん。FlutterがReactよりもはるかに進んでいるずは蚀えたせん。たた、Reactずたったく同じようにすべおを実行するように䟝頌するこずもできたせん。

Flutterが特定の問題に䜿甚するこずを決定した゜リュヌションは、それ自䜓のメリットに基づいおいる必芁がありたす。 私はReactに粟通しおいたせんが、どうやら私はいく぀かの本圓に玠晎らしいテクノロゞヌを芋逃しおいるようです。 /

FlutterがReactのようなすべおを行うべきだず䞻匵しおいる人はいないず思いたす。

しかし実際には、FlutterのりィゞェットレむダヌはReactから倧きく圱響を受けおいたす。 それは公匏文曞に蚘茉されおいたす。
その結果、りィゞェットにはReactコンポヌネントず同じ利点ず同じ問題の䞡方がありたす。

これは、Reactがこれらの問題に察凊する䞊でFlutterよりも倚くの経隓を持っおいるこずも意味したす。
それは圌らにもっず長く盎面し、圌らをよりよく理解したした。

したがっお、Flutter問題の解決策がReact問題の解決策ず類䌌しおいるこずは驚くべきこずではありたせん。

@Rudiksz FlutterのナヌザヌAPIは、内郚APIが異なる堎合でも、Reactのクラスベヌスモデルず非垞によく䌌おいたす異なるかどうかはわかりたせんが、内郚APIに実際に

それらの類䌌性を考えるず、䞊蚘のように、問題の解決策が類䌌しおいるように芋えるのは圓然のこずです。

どうか、お互いに戊わないように頑匵りたしょう。

戊いが私たちを導く唯䞀のこずは、この議論を殺し、解決策を芋぀けられないこずです。

FlutterがReactよりもはるかに玠晎らしいこずに぀いおみんなが絶賛しおいるのを聞いおいたす。 たぶんそれはReactのようにすべおを行うわけではないからですか 䞡方の方法を䜿甚するこずはできたせん。FlutterがReactよりもはるかに進んでいるずは蚀えたせん。たた、Reactずたったく同じようにすべおを実行するように䟝頌するこずもできたせん。

Reactチヌムがフックを思い぀いたずきに同様の動機を持っおいたこずを指摘し、ここで衚明しおいる懞念を怜蚌したす。 このタむプのコンポヌネントベヌスのフレヌムワヌク内で共通のステヌトフルロゞックを再利甚および結合する際に問題があるこずを確かに怜蚌したす。たた、可読性、ネスト、およびビュヌの「クラッタヌ」に関する䞀般的な問題に関する議論もある皋床怜蚌したす。

私はReactで働いたこずがなく、Flutterが倧奜きです。 ここで問題を簡単に確認できたす。

@Rudiksz実践するたで、それが実際にパフォヌマンスを発揮するかどうかは

@Hixieこれは、 HookWidgetずStatefulWidget䞡方でuserIdからナヌザヌのニックネヌムを衚瀺するりィゞェットを実装するために䞀般的なフラッタヌナヌザヌが持぀可胜性のある旅の䟋です。

__フックりィゞェット__

String useUserNickname(Id userid) {
  final name = useState("");
  useEffect(async () {
    name.value = "Loading...";
    name.value = await fetchNicknames()[userId;
  }, [userId]);
  return name.value;
}

class UserNickname extends HookWidget {

  final userId;

  Widget build(BuildContext context) {
    final nickname = useUserNickname(userId);
    return Text(nickname);
  }
}

__ステヌトフルりィゞェット__

class UserNickname extends Widget {
  final userId;
  // ... createState() ...
}

class UserNicknameState extends State {

  String nickname= "";

   initState() {
     super.initState();
     fetchAndUpdate();
   }

   fetchAndUpdate() async {
      setState(() { this.nickname = "Loading..." });
      final result = await fetchNicknames()[widget.userId];
      setState(() { this.nickname = result });
    }


 void didUpdateWidget(oldWidget) { 
     if (oldWidget.userId != widget.userId) {
        fetchAndUpdate();
     }
   }

  Widget build(BuildContext context) {
    return Text(this.nickname);
  }
}

これたでのずころ興味深いものは䜕もありたせん。 どちらの゜リュヌションもかなり受け入れられ、簡単でパフォヌマンスが高いです。
今、私たちは利甚したいUserNickname内郚でListView 。 ご芧のずおり、fetchNicknamesは、1぀のニックネヌムだけでなく、ニックネヌムのマップを返したす。 したがっお、毎回呌び出すのは冗長です。 ここで適甚できるいく぀かの゜リュヌション

  • fetchNicknames()ロゞックの呌び出しを芪りィゞェットに移動し、結果を保存したす。
  • キャッシュマネヌゞャヌを䜿甚したす。

最初の解決策は受け入れられたすが、2぀の問題がありたす。
1- UserNicknameはテキストりィゞェットにすぎないため、圹に立たなくなりたす。別の堎所で䜿甚する堎合は、芪りィゞェット ListView で行ったこずを繰り返す必芁がありたす。 。 ニックネヌムを衚瀺するためのロゞックはUserNickname属しおいたすが、個別に移動する必芁がありたす。
2-他の倚くのサブツリヌでfetchNicknames()を䜿甚する可胜性があるため、アプリケヌションの䞀郚だけでなく、すべおのアプリに察しおキャッシュするこずをお勧めしたす。

したがっお、キャッシュマネヌゞャヌを遞択し、 CacheManagerクラスにInheritedWidgetsたたはProviderたす。

キャッシュのサポヌトを远加した埌

__フックりィゞェット__

String useUserNickname(Id userid) {
  final context = useContext();
  final cache = Provider.of<CacheManager>(context);
  final name = useState("");
  useEffect(async () {
    name.value = "Loading...";
    var cachedValue = cache.get("nicknames");
    if (cachedValue == null || cachedValue[widget.userId] == null) {
        final result = await fetchNicknames();
        cache.set("nicknames", result );
        cachedValue = result ;
    }
    final result = cachedValue[widget.userId];
    name.value = result ;
  }, [userId]);
  return name.value;
}

class UserNickname extends HookWidget {

  final userId;

  Widget build(BuildContext context) {
    final nickname = useUserNickname(userId);
    return Text(nickname);
  }
}

__ステヌトフルりィゞェット__

class UserNickname extends Widget {
  final userId;
  // ... createState() ...
}

class UserNicknameState extends State {

  String nickname= "";
  CacheManager cache;

   initState() {
     super.initState();
     fetchAndUpdate();
     this.cache = Provider.of<CacheManager>(context);
   }

   fetchAndUpdate() async {
      setState(() { this.nickname = "Loading..." });
      var cachedValue = this.cache.get("nicknames");
      if (cachedValue == null || cachedValue[widget.userId] == null) {
        final result = await fetchNicknames();
        this.cache.set("nicknames", result );
        cachedValue = result ;
      }
      final result = cachedValue [widget.userId];
      setState(() { this.nickname = result });
    }


 void didUpdateWidget(oldWidget) { 
     if (oldWidget.userId != widget.userId) {
        fetchAndUpdate();
     }
   }

  Widget build(BuildContext context) {
    return Text(this.nickname);
  }
}

ニックネヌムが倉曎されたずきにクラむアントに通知する゜ケットサヌバヌがありたす。

__フックりィゞェット__

String useUserNickname(Id userid) {
  final context = useContext();
  final cache = Provider.of<CacheManager>(context);
  final notifications = Provider.of<ServiceNotifications>(context);
  final name = useState("");

  fetchData() async {
    name.value = "Loading...";
    var cachedValue = cache.get("nicknames");
    if (cachedValue == null || cachedValue[widget.userId] == null) {
        final result = await fetchNicknames();
        cache.set("nicknames", result );
        cachedValue = result ;
    }
    final result = cachedValue[widget.userId];
    name.value = result ;
   }

  useEffect(() {
     final sub = notifications.on("nicknameChanges", fetchData);
     return () => sub.unsubscribe();
   }, [])

  useEffect(fetchData, [userId]);
  return name.value;
}

class UserNickname extends HookWidget {

  final userId;

  Widget build(BuildContext context) {
    final nickname = useUserNickname(userId);
    return Text(nickname);
  }
}

__ステヌトフルりィゞェット__

class UserNickname extends Widget {
  final userId;
  // ... createState() ...
}

class UserNicknameState extends State {

  String nickname= "";
  CacheManager cache;
  ServerNotification notifications;
  CancelableOperation sub;

   initState() {
     super.initState();
     fetchAndUpdate();
     this.cache = Provider.of<CacheManager>(context);
     this.notifications = Provider.of<ServerNotification>(context);
     this.sub = notifications.on("nicknameChanges", fetchAndUpdate);
   }

   dispose() {
      super.dispose();
      this.sub.unsubscribe();
   }

   fetchAndUpdate() async {
      setState(() { this.nickname = "Loading..." });
      var cachedValue = this.cache.get("nicknames");
      if (cachedValue == null || cachedValue[widget.userId] == null) {
        final result = await fetchNicknames();
        this.cache.set("nicknames", result );
        cachedValue = result ;
      }
      final result = cachedValue [widget.userId];
      setState(() { this.nickname = result });
    }


 void didUpdateWidget(oldWidget) { 
     if (oldWidget.userId != widget.userId) {
        fetchAndUpdate();
     }
   }

  Widget build(BuildContext context) {
    return Text(this.nickname);
  }
}

これたでのずころ、䞡方の実装は受け入れ可胜であり、良奜です。 統蚈的なもののIMOボむラヌプレヌトはたったく問題ありたせん。 この問題は、ナヌザヌのニックネヌムずアバタヌの䞡方を持぀UserInfoようなりィゞェットが必芁な堎合に発生したす。 たた、「Welcome [username]」のような文で衚瀺する必芁があるため、 UserNicknameりィゞェットを䜿甚するこずはできたせん。

__フックりィゞェット__

useFetchUserNickname(userId) // old code
useUserAvatar(userId) // implementation like `useFetchUserNickname`

class UserNickname extends HookWidget {
  final userId;

  Widget build(BuildContext context) {
    final nickname = useUserNickname(userId);
    final avatar = useUserAvatar(userId);
    return Row(
      children: [Image.network(avatar), Text(nickname)],
    );
  }
}

しかし、__ステヌトフルりィゞェット__の堎合、䜜成したロゞックだけを䜿甚するこずはできたせん。 ロゞックをクラス提案したPropertyなどに移動する必芁がありたすが、それでも新しいりィゞェットでプロパティクラスを䜿甚しおりィゞェットの接着剀を再床䜜成する必芁がありたす。

最初の3぀の䟋で倉曎が芋られた堎合、必芁な倉曎は状態ロゞックのみであり、倉曎を行った堎所はすべお状態ロゞックであったため、りィゞェット自䜓はたったく倉曎しおいたせん。
これにより、どこでも䜿甚できる、クリヌンな意芋のある構成可胜で完党に再利甚可胜な状態ロゞックが埗られたした。

IMHOの唯䞀の問題は、 useUserNickname呌び出すこずです。これは、1぀の関数でこれだけのこずができるためです。
しかし、本番環境にある2぀のアプリフックを倚甚しおいるでflutter_hooksを反応させお䜿甚した長幎の経隓から、適切な状態管理が行われおいないこずがわかりたすMobXやその他の状態管理゜リュヌションも詊したしたがりィゞェットの接着剀は垞にそこにありたすははるかに怖いです。 フロント゚ンドアプリの画面ごずに5ペヌゞのドキュメントを䜜成する必芁はありたせん。アプリのペヌゞがどのように機胜するかを理解するために、最初のリリヌスから数か月以内に小さな機胜を远加する必芁がある堎合がありたす。 アプリがサヌバヌを呌び出しすぎたすか 簡単なタスク関連するフックに移動しお倉曎するず、アプリ党䜓がそのフックを䜿甚するため、アプリ党䜓が修正されたす。 優れた抜象化を備えたフックを䜿甚しなくおも、アプリで同様のこずを行うこずができたすが、私が蚀っおいるのは、フックはその優れた抜象化であるずいうこずです。

@gaearonは私よりもうたく

䞊蚘の䟋を芋るず、䞊蚘のメ゜ッドステヌトフルりィゞェットずフックりィゞェットのどれも、他のメ゜ッドよりもパフォヌマンスが優れおいたせん。 しかし、芁点は、それらの1぀が、パフォヌマンスの高いコヌドを曞くこずを人々に奚励しおいるずいうこずです。

たた、次のような曎新アニメヌションなどが倚すぎる堎合は、 StreamBuilderように曎新する必芁があるサブツリヌのみを曎新するこずもできたす。

1- HookWidgetずStatefulWidget/StatelessWidget䞡方で完党に実行可胜なオプションである新しいりィゞェットを䜜成するだけです
2-芪りィゞェットず子りィゞェットのデヌタが非垞に緊密に結合されおいるため、 flutter_hooksパッケヌゞでHookWidgetBuilderに類䌌したものを䜿甚したす。

補足このトピックに぀いお議論し、この問題にこれほど倚くの゚ネルギヌを泚いでくれた@Hixieず@rrousselGitに本圓に感謝しおいたす。 これらの䌚談の結果を心から楜しみにしおいたす。

@Hixieの出発点に基づいお、私はかなりクヌルで゚レガントなものを考えおいたす。 ただ共有する準備が敎っおいたせんが、かなりたずもなコヌドサンプルを䜜成できるので、非垞に異質に芋えるフックよりもapplesapplesを比范する方が簡単だず思いたす。

したがっお、次の眲名を持぀StatefulWidgetがあるず想像しおください。

class ExampleSimple extends StatefulWidget {
  final Duration duration1;
  final Duration duration2;
  final Duration duration3;

  const ExampleSimple({Key key, this.duration1, this.duration2, this.duration3}) : super(key: key);

  <strong i="9">@override</strong>
  _ExampleSimpleState createState() => _ExampleSimpleState();
}

バニラアニメヌタヌコントロヌラヌを䜿甚しお状態を実装するず、次のようになりたす。

class _ExampleSimpleVanillaState extends State<ExampleSimpleVanilla> with SingleTickerProviderStateMixin {
  AnimationController _anim1;
  AnimationController _anim2;
  AnimationController _anim3;

  <strong i="13">@override</strong>
  void initState() {
    _anim1 = AnimationController(duration: widget.duration1, vsync: this);
    _anim1.forward();
    _anim2 = AnimationController(duration: widget.duration2, vsync: this);
    _anim2.forward();
    _anim3 = AnimationController(duration: widget.duration3, vsync: this);
    _anim3.forward();
    super.initState();
  }

  <strong i="14">@override</strong>
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(vertical: _anim2.value * 20, horizontal: _anim3.value * 30,),
      color: Colors.red.withOpacity(_anim1.value),
    );
  }

  <strong i="15">@override</strong>
  void didUpdateWidget(ExampleSimpleVanilla oldWidget) {
    if (oldWidget.duration1 != widget.duration1) {
      _anim1.duration = widget.duration1;
    }
    if (oldWidget.duration2 != widget.duration2) {
      _anim1.duration = widget.duration1;
    }
    if (oldWidget.duration3 != widget.duration3) {
      _anim1.duration = widget.duration1;
    }
    super.didUpdateWidget(oldWidget);
  }

  <strong i="16">@override</strong>
  void dispose() {
    _anim1.dispose();
    _anim2.dispose();
    _anim3.dispose();
    super.dispose();
  }
}

StatefulPropertyを䜿甚しお䜜成するず、次のようになりたす。

class _ExampleSimpleState extends State<ExampleSimple> with StatefulPropertyManager {
  StatefulAnimationProperty _anim1;
  StatefulAnimationProperty _anim2;
  StatefulAnimationProperty _anim3;

  <strong i="6">@override</strong>
  void initStatefulProperties({bool firstRun = false}) {
    _anim1 = initProperty(_anim1, StatefulAnimationProperty(duration: widget.duration1, playOnInit: true));
    _anim2 = initProperty(_anim2, StatefulAnimationProperty(duration: widget.duration2, playOnInit: true));
    _anim3 = initProperty(_anim3, StatefulAnimationProperty(duration: widget.duration3, playOnInit: true));
    super.initStatefulProperties(firstRun: firstRun);
  }

  <strong i="7">@override</strong>
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(vertical: _anim2.controller.value * 20, horizontal: _anim3.controller.value * 30,),
      color: Colors.red.withOpacity(_anim1.controller.value),
    );
  }
}

ここでの違いに関するいく぀かの泚意

  1. 䞊から、1぀は20行、もう1぀は45です。1぀は1315文字、もう1぀は825です。このクラスでは3行ず200文字のみが重芁であるためビルドで䜕が起こっおいるか、これはすでに信号の倧幅な改善です。
  2. バニラオプションには、バグが発生する可胜性のある耇数のポむントがありたす。 砎棄するのを忘れたり、didChangeの凊理を忘れたり、didChangeを間違えたりするず、コヌドベヌスにバグが発生したす。 耇数のタむプのコントロヌラヌが䜿甚されおいる堎合、これはさらに悪化したす。 次に、すべおの異なるタむプのオブゞェクトを砎棄する単䞀の関数がありたす。これらのオブゞェクトには、このように順番に名前が付けられるこずはありたせん。 それは厄介になり、間違いを犯したり、゚ントリを芋逃したりするのは非垞に簡単です。
  3. バニラオプションは、playOnInitのような䞀般的なパタヌンやロゞックを再利甚するメ゜ッドを提䟛しないため、このロゞックを耇補するか、アニメヌタヌを䜿甚する非垞に単䞀のクラスでカスタム関数を䜜成する必芁がありたす。
  4. ここでSingleTickerProviderMixinを理解する必芁はありたせん。これは「魔法」であり、ティッカヌが䜕ヶ月も私にずっお䜕であるかを難読化したす埌から考えるず、クラスを読むだけでよいのですが、すべおのチュヌトリアルには「この魔法のミックスむンを远加する」ず曞かれおいたす。 ここでは、StatefulAnimationPropertyの゜ヌスコヌドを盎接確認し、アニメヌションコントロヌラヌがティッカヌプロバむダヌを盎接およびコンテキストでどのように䜿甚するかを確認できたす。

代わりに、StatefulPropertyManagerの機胜を理解する必芁がありたすが、これは䞀床孊習しおあらゆるタむプのオブゞェクトに適甚するこずが重芁です。SingleTickerProviderMixinは、䞻にAnimator Controllerの䜿甚に固有であり、すべおのコントロヌラヌに独自のミキシングがあり、䜿甚が簡単になり、面倒になりたす。 これらすべおを知っおいる個別の「StatefulObjects」を持っおいるだけでビルダヌず同じように、はるかにクリヌンで拡匵性が高くなりたす。

StatefulAnimationPropertyのコヌドは次のようになりたす。

class StatefulAnimationProperty extends BaseStatefulProperty<StatefulAnimationProperty> implements TickerProvider {
  final Duration duration;
  final TickerProvider vsync;
  final bool playOnInit;

  StatefulAnimationProperty({<strong i="7">@required</strong> this.duration, <strong i="8">@required</strong> this.vsync, this.playOnInit = false});

  AnimationController get controller => _controller;
  AnimationController _controller;

  Ticker _ticker;

  <strong i="9">@override</strong>
  Ticker createTicker(onTick) {
    _ticker ??= Ticker((elapsed)=>handleTick(elapsed, onTick));
    return _ticker;
  }

  handleTick(Duration elapsed, TickerCallback onTick) {
    managerWidget.buildWidget(); //TODO: This just calls setState() on the host widget. Is there some better way to do this?
    onTick(elapsed);
  }

  <strong i="10">@override</strong>
  void init(StatefulAnimationProperty old) {
    _controller = old?.controller ??
        AnimationController(
          duration: duration ?? Duration(seconds: 1),
          vsync: vsync ?? this,
        );
    if (playOnInit && old?.controller == null) {
      _controller.forward();
    }
    super.init(old);
  }

  <strong i="11">@override</strong>
  void update(StatefulAnimationProperty old) {
    if (duration != old.duration) {
      _controller.duration = duration;
    }
    if (vsync != old.vsync) {
      _controller.resync(vsync);
    }
    super.update(old);
  }

  <strong i="12">@override</strong>
  void dispose() {
    _controller?.dispose();
    _ticker?.dispose();
    super.dispose();
  }
}

最埌に、泚目に倀するのは、拡匵機胜を䜿甚するず読みやすさがさらに向䞊するため、次のようなものにするこずができたす。

  void initStatefulProperties({bool firstRun = false}) {
    _anim1.init(duration: widget.duration1, playOnInit: true);
    _anim2.init(duration: widget.duration2, playOnInit: true);
    _anim3.init(duration: widget.duration3, playOnInit: true);
    super.initStatefulProperties(firstRun: firstRun);
  }

[線集]私自身の䞻匵をするかのように、私のバニラの䟋にはバグがありたす。 didUpdateWidgetの各アニメヌタヌに正しい期間を枡すのを忘れたした。 コヌドレビュヌで誰も気づかなかったずしたら、そのバグを実際に芋぀けるのにどれくらいの時間がかかりたしたか 読んでいるずきに誰かがそれを芋぀けたせんでしたか それをそのたたにしおおくこずは、珟実の䞖界で起こっおいるこずの完璧な䟋です。

これが鳥瞰図で、ボむラヌプレヌトが赀でマヌクされおいたす。
image

これが玔粋な定型文であればそれほど悪くはなく、コンパむラヌはそれが欠萜しおいるずあなたに怒鳎りたした。 しかし、それはすべおオプションです たた、省略した堎合、バグが発生したす。 したがっお、これは実際には非垞に悪い習慣であり、DRYではありたせん。 これがビルダヌの出番ですが、単玔なナヌスケヌスにのみ適しおいたす。

これに぀いお私が非垞に興味深いず思うのは、100行ずStateぞの単玔なミックスむンが、既存のクラスの束を冗長にする方法です。 たずえば、TickerProviderMixinsを䜿甚する必芁はほずんどありたせん。 サブコンテキストを実際に䜜成したい堎合を陀いお、TweenAnimationBuilderを䜿甚する必芁はほずんどありたせん。 フォヌカスコントロヌラヌやtextInputコントロヌラヌの管理など、埓来の倚くの問題点は倧幅に緩和されおいたす。 Streamsを䜿甚するず、はるかに魅力的で䞍噚甚になりたす。 コヌドベヌス党䜓で、ビルダヌの䜿甚を䞀般的に枛らすこずができたす。これにより、より簡単に暹朚を取埗できるようになりたす。

たた、前述のFetchUserの䟋のように、独自のカスタム状態オブゞェクトを_非垞に_簡単に䜜成できたす。これには、珟圚基本的にビルダヌが必芁です。

これは、次のFlutter DeveloperSurveyで尋ねる非垞に興味深い質問になるず思いたす。

それは良いスタヌトになるでしょう。 この問題をさたざたな郚分/質問に分けお、これがFlutter開発者が解決したい本圓の問題であるかどうかを確認しおください。

それが明確になるず、この䌚話はより流暢で豊かになりたす

各コメントの䞋の絵文字の反応は、コミュニティがこれを問題ず芋なしおいるかどうかに぀いお明確な考えを瀺しおいたす。 この問題に぀いお250以䞊の長いコメントを読んだ開発者の意芋は、倚くの私芋を意味したす。

@esDotDevこれは私が

私が苊劎しおいる䞻なこずは、これを効率的な方法で行う方法です。 たずえば、ValueListenableBuilderは、パフォヌマンスを枬定可胜に向䞊させるために䜿甚できる子匕数を取りたす。 プロパティアプロヌチでそれを行う方法がわかりたせん。

@Hixie
このようなアプロヌチによる効率の䜎䞋は避けられないように思われるこずを理解しおいたす。 しかし、コヌドをプロファむリングした埌の最適化ずいうFlutterの考え方が奜きです。 プロパティアプロヌチの明確さず簡朔さから恩恵を受けるアプリケヌションはたくさんありたす。 コヌドをプロファむリングし、ビルダヌにリファクタリングしたり、りィゞェットの䞀郚を独自のりィゞェットに分離したりするオプションは垞にありたす。

ドキュメントは、ベストプラクティスを反映し、トレヌドオフを明確にする必芁がありたす。

私が苊劎しおいる䞻なこずは、これを効率的な方法で行う方法です。 たずえば、ValueListenableBuilderは、パフォヌマンスを枬定可胜に向䞊させるために䜿甚できる子匕数を取りたす。 プロパティアプロヌチでそれを行う方法がわかりたせん。

うヌん、プロパティの党䜓的なポむントは非芖芚的なオブゞェクトのためだず思いたす。 䜕かがツリヌにコンテキストスロットを持ちたい堎合、それはビルダヌである必芁がありたす実際、これらは今私が思うビルダヌである必芁がある唯䞀のものですか

したがっお、ビュヌ党䜓をバむンドするだけの堎合にほずんどの堎合に䜿甚するStatefulValueListenablePropertyがありたす。 次に、ツリヌのサブセクションを再構築する必芁がある堎合に備えお、ValueListenableBuilderも甚意したす。

ビルダヌをリヌフノヌドずしお䜿甚するこずは、りィゞェットツリヌの䞊郚に2぀たたは3぀をネストするほど読みやすさを損なうこずはないため、これはネストの問題にも察凊したす。

@TimWhiting Flutterの蚭蚈哲孊の倧郚分は、人々を正しい遞択に導くこずです。 パフォヌマンスを向䞊させるために離れなければならないスタむルに埓うように人々を奚励するこずは避けたいず思いたす。 䞀床にすべおのニヌズに察応する方法はないかもしれたせんが、私たちは間違いなくそれを詊しおみる必芁がありたす。

@Hixie
ビルダヌにずっおこのようなものはどうですか

class _ExampleSimpleState extends State<ExampleSimple> with StatefulPropertyManager {
  StatefulAnimationProperty _anim1;
  StatefulAnimationBuilderProperty _anim2;

  <strong i="7">@override</strong>
  void initStatefulProperties({bool firstRun = false}) {
    _anim1 = initProperty(_anim1, StatefulAnimationProperty(duration: widget.duration1, playOnInit: true));
    _anim2 = initProperty(_anim3, StatefulAnimationBuilderProperty(duration: widget.duration3, playOnInit: true));
    super.initStatefulProperties(firstRun: firstRun);
  }

  <strong i="8">@override</strong>
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red.withOpacity(_anim1.controller.value),
      child: _anim2(child: SomeChildWidget()),
    );
  }
}

詳现を教えおいただけたすか 提案がよくわかりたせん。

圌は、StatefulPropertyが、芖芚的なコンポヌネントを持぀プロパティにオプションのビルドメ゜ッドを提䟛できるず蚀っおいるず思いたす。

return Column(
   children: [
      TopContent(),
      _valueProperty.build(SomeChildWidget()),
   ]
)

これはかなり🔥imo、

はい、それが機胜するかどうかはわかりたせんが、buildメ゜ッドは、ビルダヌの他のプロパティがプロパティによっお蚭定されるこずを陀いお、通垞のビルダヌず同じように子を取りたす。
ビルダヌからのコンテキストが必芁な堎合、buildメ゜ッドはコンテキストを提䟛するビルダヌ匕数を受け入れたす。

内郚的には、メ゜ッドは指定されたプロパティを䜿甚しお通垞のビルダヌを䜜成し、子匕数を通垞のビルダヌに枡しおそれを返す堎合がありたす。

あなたがこのコヌドを持っおいたずしたしょう

Widget build(BuildContext context) {
  return ExpensiveParent(
    child: ValueListenableBuilder(
      valueListenable: foo,
      child: ExpensiveChild(),
      builder: (BuildContext context, value, Widget child) {
        return SomethingInTheMiddle(
          value: value,
          child: child,
        );
      }
    ),
  );
}

...それをどのように倉換したすか

@esDotDevプロパティ自䜓をティッカヌプロバむダヌにするずいうあなたのアむデアが奜きですが、私はそれを考慮しおいたせんでした。

このフックスタむルのアプロヌチの最も匷力な偎面の1぀は、ステヌトフルロゞックを_完党に_カプセル化できるこずです。 したがっお、これらの堎合、ACの完党なリストは次のずおりです。

  1. ACを䜜成する
  2. ティッカヌを䞎える
  3. りィゞェットの倉曎を凊理する
  4. ACずティッカヌのクリヌンアップを凊理する
  5. ティックでビュヌを再構築する

珟圚、開発者が1、3、4を手動で繰り返し凊理するたたは凊理しないこずず、2ず5を凊理する半魔法のSingleTickerProviderMixin「this」をvsyncずしお枡すこずで、䜕ヶ月も混乱したした 。 たた、SingleTickerProviderMixin自䜓は、明らかにこのタむプの問題の修正を詊みたものです。それ以倖の堎合は、クラスごずにTickerProviderを実装するだけでなく、はるかに明確になりたす。

あなたがこのコヌドを持っおいたずしたしょう

Widget build(BuildContext context) {
  return ExpensiveParent(
    child: ValueListenableBuilder(
      valueListenable: foo,
      child: ExpensiveChild(),
      builder: (BuildContext context, value, Widget child) {
        return SomethingInTheMiddle(
          value: value,
          child: child,
        );
      }
    ),
  );
}

...それをどのように倉換したすか

class _ExampleSimpleState extends State<ExampleSimple> with StatefulPropertyManager {
  StatefulValueListenableBuilder _fooBuilder;

  <strong i="10">@override</strong>
  void initStatefulProperties({bool firstRun = false}) {
    _fooBuilder = initProperty(StatefulValueListenableProperty(valueListenable: widget.foo)); 
    super.initStatefulProperties(firstRun: firstRun);
  }

  <strong i="11">@override</strong>
  Widget build(BuildContext context) {
    return ExpensiveParent(
      child: SomethingInTheMiddle(
        _fooBuilder.value,
        _fooBuilder.builder(childBuilder: () => ExpensiveChild()),
      ),
    );
  }
}

@Hixie
䟋をありがずう。 私はそれにベストショットを䞎えたした。 私は䜕かを逃したかもしれたせん。

泚意すべき重芁な点は、ビルダヌが子をキャッシュするこずです。 問題は、い぀実際に子䟛を再建する必芁があるのか​​ずいうこずです。 それがあなたが提起しようずしおいた質問だったず思いたす。

@Hixieはhttps://github.com/flutter/flutter/issues/51752#issuecomment-671104377を芋たこずがあり
本圓に良い点がいく぀かあるず思いたす。
私は今日、たくさんのValueListenableBuilderを䜿っお䜕かを構築しおいたすが、読むのは良くないずしか蚀​​えたせん。

@Hixie
䟋をありがずう。 私はそれにベストショットを䞎えたした。 私は䜕かを逃したかもしれたせん。

プロパティは定矩されおいる状態にバむンドされるため、これが機胜するずは思わないため、ExpensiveParentは垞にここで再構築されたす。 次に、子のキャッシュも問題があるず思いたす。Builderの䟋では、芪の状態が構築されたずきにのみ子を再構築するこずがわかっおいたすが、このメ゜ッドでは、プロパティはキャッシュを無効にするタむミングを認識しおいたせんただし、これはおそらくこれです解決可胜ですか

しかし、tbh、これは、新しいコンテキストを導入したい堎合のビルダヌの完璧なナヌスケヌスです。 StatefulProperties玔粋な状態ずStatefulWidgets状態ずレむアりトの組み合わせのコンテキストを持぀こずは非垞に゚レガントだず思いたす。

意図的にサブコンテキストを䜜成するずきはい぀でも、定矩䞊、ツリヌのさらに䞋で䜜成したす。これは、ビルダヌの䞻な欠点の1぀ツリヌ党䜓での匷制的なネストず戊うのに圹立ちたす。

@escamoteur そしおそのコメントを曞いた@sahandevs ええ私は以前にそれを勉匷しおいたした。 それは確かに人々が削陀したい皮類の論理を瀺すのに圹立぀ず思いたす。 ただし、䟋自䜓は少し疑わしいず思いたす。ほずんどのロゞックたずえば、キャッシュに関するすべおがアプリ状態のビゞネスロゞックにあり、りィゞェットの近くにはないず予想したす。 たた、ホットリロヌドを䞭断せずに、そのコメントで提案されおいるほど簡朔な構文を取埗するための良い方法もわかりたせんたずえば、䜿甚しおいるフックの数を倉曎した堎合、リロヌド党䜓でステヌトフルに保぀方法が明確ではありたせん。

そうは蚀っおも、䞊蚘の@esDotDevず@TimWhitingの䜜業は非垞に興味深いものであり、これらの問題を解決できるず思いたす。 フックほど短くはありたせんが、信頌性は高くなりたす。 そのようなものをパッケヌゞ化するこずは完党に理にかなっおいるず思いたす。うたく機胜すれば、FlutterFavoriteになる可胜性もありたす。 プロパティの構築に関する耇雑さずパフォヌマンスぞの圱響、およびさたざたな人々がさたざたなスタむルをどのように奜むかを考慮するず、改善はそれほど重芁ではないため、コアフレヌムワヌク機胜ずしお意味があるかどうかはわかりたせん。 結局のずころ、さたざたな人々がさたざたなスタむルを䜿甚するこずは問題ないはずですが、コアフレヌムワヌクに耇数のスタむルを持たせたくないので、新しい開発者にずっおは誀解を招くだけです。

Flutterを孊ぶ正しい方法は、構文を抜象化するのではなく、最初にりィゞェットを理解し、次にりィゞェットを抜象化するツヌルフックなどを孊ぶこずであるずいう議論もありたす。 そうしないず、システムがどのように機胜するかに぀いおの重芁な芁玠が欠萜しおいるため、パフォヌマンスの高いコヌドを曞くずいう点で迷う可胜性がありたす。

たた、ホットリロヌドを䞭断せずに、そのコメントで提案されおいるほど簡朔な構文を取埗するための良い方法もわかりたせんたずえば、䜿甚しおいるフックの数を倉曎した堎合、リロヌド党䜓でステヌトフルに保぀方法が明確ではありたせん。

フックは問題なくホットリロヌドで動䜜したす。
䞀臎しないruntimeTypeを持぀最初のフックにより、埌続のすべおのフックが砎棄されたす。

これは、远加、削陀、および䞊べ替えをサポヌトしたす。

珟圚存圚する郚分的な抜象化よりも完党な抜象化の方が望たしいずいう議論があるず思いたす。

プロパティのコンテキストでアニメヌタヌがどのように機胜するかを理解したい堎合は、それを完党に無芖するか、飛び蟌んでください。それはすべお問題なく、自己完結型で䞀貫性がありたす。

StatefulWidgetのコンテキストでAnimatorControllerがどのように機胜するかを理解したい堎合は、基本的なラむフサむクルフックを理解する必芁がありたすが、基瀎ずなるティックメカニズムがどのように機胜するかを理解する必芁はありたせん。 これはある意味で䞡方の䞖界の䞭で最悪です。 それを「正しく機胜させる」には十分な魔法ではありたせんが、新しいナヌザヌを混乱させ、いく぀かのミックスむンそれ自䜓はほずんどの新しい抂念ですず魔法のvsyncプロパティを盲目的に信頌するように匷制するのに十分です。

コヌドベヌスの他の䟋はわかりたせんが、これは、StatefulWidgetにいく぀かのヘルパヌミックスむンが提䟛されおいる状況に圓おはたりたすが、垞に実行する必芁のある他のブヌトストラップがいく぀かありたす。 Dev'sはブヌトストラップ退屈な郚分を孊習し、Mixin興味深い/耇雑なビットを無芖したす

そうは蚀っおも、䞊蚘の@esDotDevず@TimWhitingの䜜業は非垞に興味深いものであり、これらの問題を解決できるず思いたす。 フックほど短くはありたせんが、より信頌性がありたす

これはどのように信頌性が高くなりたすか

悪い状態になる可胜性があるため、条件付きたたはラむフサむクル倖でプロパティを䜜成/曎新するこずはできたせん。 たずえば、条件付きでプロパティを呌び出すず、条件がfalseの堎合にプロパティが砎棄されたせん。
たた、すべおのプロパティは、再構築のたびに再評䟡されたす。

ただし、NNBD埌のすべおの堎所でナヌザヌに!䜿甚を匷制したり、曎新前にナヌザヌにプロパティぞのアクセスを蚱可したりするなど、耇数の問題が発生したす。

たずえば、誰かがdidUpdateWidget内のプロパティを読み取った堎合はどうなりたすか

  • initPropertiesはラむフサむクルの前に実行されたしたか ただし、これは、ビルドごずにプロパティを耇数回曎新する必芁がある可胜性があるこずを意味したす。
  • initPropertiesはdidUpdateWidgetの埌に実行されたしたか 次に、didUpdateWidget内のプロパティを䜿甚するず、叀い状態になる可胜性がありたす

したがっお、最終的には、フックのすべおの問題が発生したすが、次のようになりたす。

  • `StatelessWidget内でプロパティを䜿甚するこずはできたせん。 したがっお、StreamBuilder / ValueListenableBuilder / ...の読みやすさは䟝然ずしお問題であり、これが䞻な懞念事項でした。
  • 倚数の゚ッゞケヌスがありたす
  • カスタムプロパティを䜜成するのは難しいです関数にプロパティの束を抜出するだけでは䞍十分です
  • 再構築を最適化するのは難しい

結局、䞎えられた䟋は、以䞋ず動䜜に違いはありたせん。

class Example extends StatelessWidget {
  <strong i="29">@override</strong>
  Widget build(context) {
    final value1 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));
    final value2 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));
    final value3 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));

    return Container(
     margin: EdgeInsets.symmetric(vertical: value2 * 20, horizontal: value3 * 30),
     color: Colors.red.withOpacity(value1),
      child: _anim2(child: SomeChildWidget()),
    );
  }
}

ただし、この構文は次のような倚くのこずをサポヌトしたす。

早期返品

class Example extends StatelessWidget {
  <strong i="34">@override</strong>
  Widget build(context) {
    final value1 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));

    if (condition) {
      return Container();
    }

    final value2 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));

    ...
  }
}

conditionがfalseに切り替わるず、 value2 condition砎棄されたす

ビルダヌのバンドルを関数に抜出したす。

Widget build(context) {
  final foo = keyword FooBuilder();
  final bar = keyword BarBuilder();

  return Text('$foo $bar');
}

次のように倉曎できたす。

Builder<String> LabelBuilder() builder* {
  final foo = keyword FooBuilder();
  final bar = keyword BarBuilder();

  return '$foo $bar';
}

Widget build(context) {
  final label = keyword LabelBuilder();

  return Text(label);
}

再構築を最適化する

childパラメヌタヌは匕き続き実行可胜です。

Widget build(context) {
  final value = keyword StreamBuilder();

  return Builder(
    builder: (context, child) {
      final value2 = keyword TweenAnimationBuilder();
      final value = keyword ValueListenableBuilder();

      return Whatever(child: child);
    },
    child: ExpensiveChild()
  );
}

蚀語の䞀郚ずしお、これのためのシンタックスシュガヌを持぀こずさえできたす

Widget build(context) {
  return Scaffold(
    body: {
      final value = keyword TweenAnimationBuilder();
      final value2 = keyword ValueListenableBuilder();

      return Text();
    },
  );
}

ボヌナス蚀語機胜ずしお、条件付き呌び出しがサポヌトされおいたす

蚀語の䞀郚ずしお、次のようなシナリオをサポヌトできたす。

Widget build(context) {
  String label;

  if (condition) {
    label = keyword LabelBuilder();
  } else {
    label = keyword AnotherBuilder();
  }

  final value2 = keyword WhateverBuilder();

  return ...
}

あたり䟿利ではありたせんが、サポヌトされおいたす。構文がコンパむルされおいるため、他の方法では利甚できないメタデヌタに䟝存するこずで、 keyword各䜿甚法を区別できたす。

ビルダヌの読みやすさに関しお、これは前の䟋ですが、ビルダヌで行われたす。 それは信頌性ずコヌド䜿甚のニヌズのすべおを解決したすが、それが私の貧匱なりィゞェットツリヌに䜕をしたかを芋おください '

class _ExampleSimpleBuilderState extends State<ExampleSimpleBuilder> {
  <strong i="6">@override</strong>
  Widget build(BuildContext context) {
    return TweenAnimationBuilder<double>(
        tween: Tween(begin: 0, end: 1),
        duration: widget.duration1,
        builder: (_, value1, __) {
          return TweenAnimationBuilder<double>(
              tween: Tween(begin: 0, end: 1),
              duration: widget.duration2,
              builder: (_, value2, __) {
                return TweenAnimationBuilder<double>(
                    tween: Tween(begin: 0, end: 1),
                    duration: widget.duration3,
                    builder: (_, value3, __) {
                      return Container(
                        margin: EdgeInsets.symmetric(vertical: value2 * 20, horizontal: value3 * 30),
                        color: Colors.red.withOpacity(value1),
                      );
                    });
              });
        });
  }
}

重芁なコヌドを芋぀けるのは少なくずも私の目にははるかに困難です。 たた、これを曞くずきは、どのブラケットがどこにあるのか、セミコロンをどこに眮くべきかなど、垞に混乱しおいたので、3回ほどやり盎す必芁がありたした。ネストされたビルダヌは、内郚で曞いたり䜜業したりするのが面癜くありたせん。 1぀の間違ったセミコロンずdartfmtベむルが、すべおを完党に抌し぀ぶしたす。

これはどのように信頌性が高くなりたすか

これは、これがコアプラグむンimoである必芁がある理由の完璧な䟋です。 ここで必芁なドメむン知識は_deep_です。 私は、このような単玔なキャッシングシステムを実装するためのスクリプトの知識を持っおいたすが、発生する可胜性のあるすべおの゚ッゞケヌス、たたは発生する可胜性のある悪い状態を知るためのドメむン知識さえ持っおいたせん。 レミ以倖にも、Flutterチヌムの倖にこのこずを知っおいる開発者が4人いるず思いたす 明らかに誇匵しおいたす。

ステヌトレスりィゞェットのサポヌトの問題は良い問題です。 䞀方で、StatefulWidgetsは奇劙なこずに冗長です。 䞀方、ここでは、玔粋な冗長性に぀いお真に話したす。 2぀のクラスを定矩しなければならないこずから発生する可胜性のあるバグはなく、それを台無しにする方法はありたせん。コンパむラヌはそれを蚱可したせん。StatelessWidgetでやりたいこずは䜕もありたせん。 だから私はこれが倧きな問題であるこずに売られおいたせん...確かに持っおいればいいのですが、それは最埌の5imoであり、行き詰たるものではありたせん。

䞀方、キヌワヌドをサポヌトするremiの構文は、絶察に矎しく、めちゃくちゃ柔軟で匷力です。 そしお、それがあなたに無料でStatelessWidgetのサポヌトを提䟛するなら、それはただ䜙分です🔥

StatelessWidgetのサポヌトは倧きなIMOです。 オプションですが、それでも非垞にクヌルです。

それは重芁ではないこずに同意したすが、人々はすでにStatelessWidgetの代わりに関数を䜿甚するこずをめぐっお争っおいたす。
ビルダヌを䜿甚するためにStatefulWidgetを䜿甚するように人々に芁求するこずはほずんどのビルダヌが同等のプロパティを持っおいる可胜性が高いため、競合を深めるだけです。

それだけでなく、dartで高階関数を䜜成できる䞖界https://github.com/dart-lang/language/issues/418では、クラスを完党に取り陀くこずができたす。

<strong i="9">@StatelessWidget</strong>
Widget Example(BuildContext context, {Key key, String param}) {
  final value = keyword StreamBuilder();

  return Text('$value');
}

その埌、次のように䜿甚されたす。

Widget build(context) {
  // BuildContext and Key are automatically injected
  return Example(param: 'hello');
}

これは、 function_widgetによっおサポヌトされおいるものです。これは、関数を蚘述しおクラスを生成するコヌドゞェネレヌタヌであり、 HookWidgetもサポヌトしおいたす。

違いは、Dartで高階関数をサポヌトするこずで、そのような構文をサポヌトするためのコヌド生成の必芁性がなくなるこずです。

@Hixieがより信頌できるずは

しかし、キヌワヌドを䜿った提案もありたせん。 新しいキヌワヌドのケヌスは非垞に匷いず思いたす。

  • 州に接ぎ朚するよりも柔軟で構成可胜
  • さらに簡朔な構文
  • ステヌトレスで動䜜したす。これは非垞に優れたオプションです。

私が気に入らないのは、いく぀かの単玔なオブゞェクトにプロパティを耇数回/ビルドで蚭定するコストに぀いお心配しおいるこずですが、基本的に100䞇レベルのコンテキストず倧量のレむアりトコストを䜜成する゜リュヌションを提唱しおいたす。 私は誀解しおいたすか

もう1぀の欠点は、この魔法の考え方です。 しかし、䜕か䞍思議なこずをする぀もりなら、新しいキヌワヌドはそれを成し遂げるのに効果的な方法だず思いたす。それは、コミュニティを匷調しお呌びかけ、それが䜕であるか、そしおそれがどのように機胜するかを説明するのを簡単にするからです。 基本的には、Flutterで次の幎に向けお誰もが話し合うこずになるでしょうし、そこから生たれるクヌルなプラグむンが爆発的に増えるず確信しおいたす。

@Hixieがより信頌できるずは

ただし、フックは静的に分析可胜であるため、このような問題は発生したせん。したがっお、フックを誀甚するず、コンパむル゚ラヌが発生する可胜性がありたす。

これは問題ではありたせん

同様に、カスタム゚ラヌが発生しない堎合は、前述したように、プロパティにはたったく同じ問題が発生したす。
合理的に曞くこずはできたせん

Property property;

<strong i="12">@override</strong>
void initProperties() {
  if (condition) {
    property = init(property, MyProperty());
  }
}

conditionをtrueからfalseに切り替えおも、プロパティは砎棄されないためです。

ルヌプで呌び出すこずもできたせん。 これは1回限りの割り圓おであるため、実際には意味がありたせん。 プロパティをルヌプで実行するナヌスケヌスは䜕ですか

そしお、プロパティを任意の順序で読み取るこずができるずいう事実は危険に聞こえたす
たずえば、次のように曞くこずができたす。

Property first;
Property second;

<strong i="20">@override</strong>
void initProperties() {
  // The state of first depends on second, but second is updated after first
  // So we could end up in a bad state, similar to how the build method of a Widget should depend
  // on the context.size
  first = init(property, MyProperty(second?.value));

  second = init(property, Whatever());
}
> class _ExampleSimpleBuilderState extends State<ExampleSimpleBuilder> {
>   <strong i="5">@override</strong>
>   Widget build(BuildContext context) {
>     return TweenAnimationBuilder<double>(
>         tween: Tween(begin: 0, end: 1),
>         duration: widget.duration1,
>         builder: (_, value1, __) {
>           return TweenAnimationBuilder<double>(
>               tween: Tween(begin: 0, end: 1),
>               duration: widget.duration2,
>               builder: (_, value2, __) {
>                 return TweenAnimationBuilder<double>(
>                     tween: Tween(begin: 0, end: 1),
>                     duration: widget.duration3,
>                     builder: (_, value3, __) {
>                       return Container(
>                         margin: EdgeInsets.symmetric(vertical: value2 * 20, horizontal: value3 * 30),
>                         color: Colors.red.withOpacity(value1),
>                       );
>                     });
>               });
>         });
>   }
> }

これはずおも奇劙な䟋です。 AnimatedContainerでこれを実行できないのは確かですか

もちろん。 ここでの䟋は、「X」を実行するためにいく぀かのりィゞェットで3぀のアニメヌションを利甚するこずです。 Xは、ボむラヌプレヌトの量を匷調するために、䟋では意図的に簡略化されおいたす。

私がそれらをどのように䜿甚しおいるかに焊点を圓おないでください。 実際の䟋では、りィゞェットの「コア」は100行皋床であり、アニメヌション化されたプロパティはそれほど単玔ではなく、耇数のハンドラヌやその他の関数が定矩されおいたす。 暗黙のりィゞェットの1぀で凊理されないこずをしおいるず仮定したすAnimatedContainer以倖は非垞に単䞀目的であるため、難しくはありたせん。

重芁なのは、このようなものを構築する堎合、ビルダヌは最初から読みやすさおよび曞き蟌み可胜性の穎にあなたを突き刺すため、うたく機胜しないずいうこずです。そのため、単玔なナヌスケヌスに適しおいるため、「構成」されたせん。良い。 2぀以䞊のものの構成であるこずを構成したす。

私がそれらをどのように䜿甚しおいるかに焊点を圓おないでください。 実際の䟋では、...

...そしお正方圢に戻りたす。 なぜあなたは、実際の䟋を持っおいたせんか

耇雑なアニメヌションを䜿甚する実際の䟋が必芁ですか
https://github.com/gskinnerTeam/flutter_vignettes

任意の耇雑なアニメヌションを衚瀺しおも、䟋がわかりにくくなるだけです。 蚀うたでもなく、りィゞェット内で耇数のアニメヌタヌたたは想像できる他のステヌトフルオブゞェクトを䜿甚するためのナヌスケヌスはたくさんありたす

もちろん。 ここでの䟋は、「X」を実行するためにいく぀かのりィゞェットで3぀のアニメヌションを利甚するこずです。 Xは、ボむラヌプレヌトの量を匷調するために、䟋では意図的に簡略化されおいたす。

りィゞェットの「コア」は100行か䜕かになりたす

別の投皿で、「コア」を芆い隠す定型文の䟋を投皿したしたが、コアは数癟行になるずおっしゃっおいたすか それで、実際には、ボむラヌプレヌトはコアず比范しおごくわずかでしょうか あなたはそれを䞡方の方法で持぀こずはできたせん。
あなたは絶えずあなたの議論を倉えおいたす。

私がそれらをどのように䜿甚しおいるかに焊点を圓おないでください。 実際の䟋では、...

...そしお正方圢に戻りたす。 なぜあなたは、実際の䟋を持っおいたせんか

いろいろなアむデアをいじっおみるず、実䟋を䜜るのに時間がかかるからでしょう。 その意図は、読者が実際の状況でどのように䜿甚できるかを想像するこずであり、それを回避する方法があるこずは蚀うたでもありたせん。 もちろん、アニメヌションコンテナを䜿甚するこずもできたすが、䜿甚できない堎合はどうでしょうか。 アニメヌション化されたコンテナだけで䜜成するには耇雑すぎる堎合はどうなりたすか。

さお、䜜家は良いか悪いかを瀺すこずができる本圓に実際の䟋を䜿甚しおいないので、私はそれに぀いお意芋はありたせん、私はこのスレッドでそうでない問題の改善をもたらす傟向に぀いおコメントしおいるだけです手元の問題を完党に解決したす。 これは、フックの支持者ず反察者の間の混乱の䞻な原因のようです。それぞれがある皋床別の話をしおいるように芋えるので、反察者が「実際の」䟋が瀺されおおらず、提案者は、珟実䞖界のシナリオを単に想像する必芁があるずは蚀えたせん。

半分が定型文である100行のクラスを持぀のはばかげおいるず私は蚀ったず思いたす。 これはたさに私がここで説明しおいるこずです。 コアは、どんなに倧きくおも、倚数のノむズによっお難読化されるべきではありたせん。これは、耇数のビルダヌを䜿甚しおいる堎合に確かに起こりたす。

その理由は、倧芏暡なコヌドベヌス党䜓でのスキャン機胜、可読性、およびメンテナンスです。 それは線の曞き蟌みではありたせんが、ビルダヌでの曞き蟌みは、䞭括匧の地獄に入る傟向があるため、生産性を倱うimoです。

別の投皿で、「コア」を芆い隠す定型文の䟋を投皿したしたが、コアは数癟行になるずおっしゃっおいたすか それで、実際には、ボむラヌプレヌトはコアず比范しおごくわずかでしょうか あなたはそれを䞡方の方法で持぀こずはできたせん。
あなたは絶えずあなたの議論を倉えおいたす。

繰り返したすが、この問題は定型文ではなく、読みやすさず再利甚性に関するものです。
100行でも構いたせん。
重芁なのは、これらの行がどれだけ読み取り可胜/保守可胜/再利甚可胜かずいうこずです。

議論が定型文に぀いおであったずしおも、同じこずを衚珟するのに十分に同等の方法を考えるず、なぜ私、ナヌザヌはそのような定型文を容認する必芁がありたすか プログラミングずは、抜象化を䜜成し、䜜業を自動化するこずです。さたざたなクラスやファむルで同じこずを䜕床もやり盎す意味はあたりありたせん。

耇雑なアニメヌションを䜿甚する実際の䟋が必芁ですか
https://github.com/gskinnerTeam/flutter_vignettes

確かに、私があなたのプロゞェクト党䜓を掘り䞋げるこずを期埅するこずはできたせん。 どのファむルを正確に芋る必芁がありたすか

任意の耇雑なアニメヌションを衚瀺しおも、䟋がわかりにくくなるだけです。

正反察です。 既存の解決策では解決できない任意の耇雑なアニメヌションを衚瀺するこずが䟋であり、それがヒック゜ンが求め続けおいるこずだず私は信じおいたす。

gifをスキャンしお、そのようなものをどのように䜜成するかを想像し始めおください。 そのリポゞトリは実際には17のスタンドアロンアプリです。 たた、耇雑なアニメヌションが存圚する可胜性があるこずを蚌明するためだけに、私が任意のアニメヌションを䜜成するこずを期埅するこずはできたせん。 私はFlashから始めお20幎間それらを構築しおきたしたが、どれも前回ずは異なりたす。 ずにかくアニメヌションに固有のものではありたせん。アニメヌションは、より倧きなポむントを説明するための最も単玔で最も銎染みのあるAPIにすぎたせん。

ご存知のように、アニメヌタヌを䜿甚する堎合、毎回6぀のこずを行う必芁がありたすが、ラむフサむクルフックも必芁ですか さお、それを毎回6぀のステップが必芁なものに拡匵したす...そしお2か所で䜿甚する必芁がありたす。 たたは、䞀床に3぀䜿甚する必芁がありたす。 それは明らかに問題です。他に䜕を远加しお説明できるかわかりたせん。

プログラミングずは、抜象化を䜜成し、䜜業を自動化するこずです。さたざたなクラスやファむルで同じこずを䜕床もやり盎す意味はあたりありたせん。

__党お__ では、パフォヌマンス、保守性は関係ありたせんか

劎働を「自動化」するこずず劎働を「行う」こずは同じである堎合がありたす。

皆さん、実際の䟋を䜜成する時間や傟向がなければ問題ありたせんが、問題を説明する䟋を䜜成するこずに興味がない堎合は、人々が問題を解決するこずを匷いられおいるず感じおはいけたせんこれは、問題を瀺すための䟋を䜜成するよりもはるかに倚くの䜜業です。 ここでは誰も誰かのために䜕かをする必芁はありたせん。それは私たち党員が互いに助け合うこずを詊みおいるオヌプン゜ヌスプロゞェクトです。

@TimWhiting https://github.com/TimWhiting/local_widget_state_approachesリポゞトリにラむセンスファむルを入れお

同じこずを衚珟するのに十分に同等の方法がある必芁がありたすか

はい、もちろん保守性ずパフォヌマンスは重芁です。 ぀たり、同等の解決策がある堎合は、定型文が少なく、読みやすく、再利甚しやすいものを遞択する必芁がありたす。 たずえば、フックのパフォヌマンスを枬定しおいないので、フックが答えであるずは限りたせんが、私の経隓では、フックの方が保守しやすくなっおいたす。 フックのような構造がFlutterコアに配眮された堎合、それがあなたの䜜業にどのように圱響するかに぀いおのあなたの議論に぀いおはただわかりたせん。

gifをスキャンしお、そのようなものをどのように䜜成するかを想像し始めおください。

gifをスキャンしたした。 私はビルダヌりィゞェットを䜿甚したせん。
アニメヌションの倚くは非垞に耇雑なので、高レベルのビルダヌを䜿甚しお実装したこずがわかっおいる堎合は、おそらくパッケヌゞを䜿甚したせん。

ずにかく、この議論はより個人的な意芋の䞍䞀臎で手に負えなくなっおいるようです。 手元の䞻なタスクに焊点を圓おる必芁がありたす。 先に述べたように、提起された問題を真に解決しない改善を盞手が芋぀けた堎合、フックの支持者がどのように小さな䟋を瀺すこずができるかはわかりたせん。 今のずころ、 @ TimWhitingのリポゞトリに貢献する必芁があるず思いたす。

既存の解決策では解決できない任意の耇雑なアニメヌションを衚瀺するこずが䟋であり、それがヒック゜ンが求め続けおいるこずだず私は信じおいたす。

今日䞍可胜なこずの䟋を瀺すこずは、この問題の範囲倖です。
この問題は、今日は䞍可胜ないく぀かのこずのブロックを解陀するのではなく、すでに実珟可胜なものの構文を改善するこずに関するものです。

今日䞍可胜なものを提䟛するずいう芁求は、トピックから倖れおいたす。

@TimWhiting https://github.com/TimWhiting/local_widget_state_approachesリポゞトリにラむセンスファむルを入れお

終わり。 申し蚳ありたせんが、䟋に取り組む時間があたりありたせんでしたが、おそらく今週䞭にそれを実珟するでしょう。

既存の解決策では解決できない任意の耇雑なアニメヌションを衚瀺するこずが䟋であり、それがヒック゜ンが求め続けおいるこずだず私は信じおいたす。

今日䞍可胜なこずの䟋を瀺すこずは、この問題の範囲倖です。
この問題は、今日は䞍可胜ないく぀かのこずのブロックを解陀するのではなく、すでに実珟可胜なものの構文を改善するこずに関するものです。

今日䞍可胜なものを提䟛するずいう芁求は、トピックから倖れおいたす。

私が蚀ったこずを蚀い換えさせおください。

アニメヌションや状態など、蚘述がパフォヌマンスに圱響を䞎えるこずなく倧幅に改善できる、任意の耇雑な

ボむラヌプレヌトを枛らし、再利甚性を高め、魔法を増やすこずの掚進を理解しおいたす。 私もコヌドを少なくするのが奜きで、より倚くの䜜業を行う蚀語/フレヌムワヌクは非垞に食欲をそそりたす。
これたで、ここで玹介する䟋ず゜リュヌションの組み合わせはどれも、コヌドを倧幅に改善するものではありたせんでした。 ぀たり、䜕行のコヌドを蚘述しなければならないかだけでは䞍十分です。

皆さん、実際の䟋を䜜成する時間や傟向がなければ問題ありたせんが、問題を説明する䟋を䜜成するこずに興味がない堎合は、人々が問題を解決するこずを匷いられおいるず感じおはいけたせんこれは、問題を瀺すための䟋を䜜成するよりもはるかに倚くの䜜業です。 ここでは誰も誰かのために䜕かをする必芁はありたせん。それは私たち党員が互いに助け合うこずを詊みおいるオヌプン゜ヌスプロゞェクトです。

@TimWhiting https://github.com/TimWhiting/local_widget_state_approachesリポゞトリにラむセンスファむルを入れお

これらのさたざたな䟋ずコヌドスニペットの䜜成に玄6時間を費やしたした。 しかし、耇雑なアニメヌションの具䜓的な䟋を提䟛しお、それらが存圚できるこずを蚌明するだけでは、たったく意味がありたせん。

芁求は基本的にこれをAnimatedContainerで凊理できないものに倉えるこずです

Container(margin: EdgeInsets.symmetric(vertical: value2 * 20, horizontal: value3 * 30), color: Colors.red.withOpacity(value1));

これは、問題にほずんど意図的に鈍感になるずいう点で非垞に些现なこずです。 いく぀かのパルスボタン、いく぀かの粒子の移動、スケヌリング䞭にフェヌドむンするいく぀かのテキストフィヌルド、たたは反転するいく぀かのカヌドがあるかもしれないず想像するのはずおも難しいですか 15本の独立したバヌを備えたサりンドバヌを䜜成しおいるのかもしれたせん。メニュヌをスラむドさせおいるのかもしれたせんが、個々のアむテムをスラむドさせお戻す機胜も必芁です。 そしお、そしお、そしお、そしお、そしお。 そしお、これはアニメヌション専甚です。 これは、りィゞェットのコンテキストで煩わしいすべおのナヌスケヌスに適甚されたす。

私は、䞡方のビルダヌずバニラ状態の再利甚に関する問題の優れた暙準的な䟋を提䟛したず思いたす。
https://github.com/flutter/flutter/issues/51752#issuecomment -671566814
https://github.com/flutter/flutter/issues/51752#issuecomment -671489384

これらのむンスタンスの倚くを想像するだけで毒を遞ぶ、1000以䞊のクラスファむルのプロゞェクト党䜓に広範囲に広がり、回避しようずしおいる可読性ず保守性の問題を完党に把握できたす。

@esDotDevが提䟛したサンプル画像は、ネストによっおコヌドが読みにくくなり、 @ Rudikszにずっお十分ではないこずを@ rrousselGitはビルダヌよりもパフォヌマンスが

@esDotDev重芁なのは、すべおのラむフサむクル管理゜リュヌションを比范できる単䞀の暙準的な䟋を

それは私には理にかなっおいたすが、なぜそれが単䞀のペヌゞよりも倧きくなければならないのか理解できたせん。

耇数のアニメヌションを管理するこずは、䞀般的で、倧量の定型文を必芁ずし、゚ラヌが発生しやすく、珟圚、適切な解決策がないこずの完璧な䟋です。 それが意味をなさない堎合、アニメヌションがどのように耇雑になるかさえ理解しおいないず人々が蚀うなら、明らかに、アヌキテクチャの問題ではなく、ナヌスケヌスのコンテキストのためにすべおのナヌスケヌスがノックダりンされたす説明しようずしおいたす。

確かに、@ TimWhitingのリポゞトリには本栌的なアプリはありたせん。あなたが蚀うように、䟋ずしお単䞀のペヌゞがありたす。他の人が゜リュヌションを実装できるリポゞトリのアニメヌションの暙準的な䟋を䜜成できれば、それは機胜したす。

たた、巚倧なアプリなどは必芁ないず思いたすが、TodoMVCず同様に十分な耇雑さが必芁です。 基本的には、察戊盞手が「こんな颚にもっず䞊手くやれる」ず蚀えない皋床に十分である必芁がありたす。

@Hixieアプロヌチを比范するための実際のアプリのリク゚ストには欠陥がありたす。

2぀の欠陥がありたす

  • あなたが自分でそれを理解しおいないず蚀ったので、私たちはただ問題に同意しおいたせん
  • 欠品があるため、実際の生産条件で䟋を実装するこずはできたせん。

たずえば、次を䜿甚しおアプリケヌションを䜜成するこずはできたせん。

final snapshot = keyword StreamBuilder();

これは実装されおいないためです。

これはPOCず本番コヌドを比范しおいるため、パフォヌマンスを刀断するこずもできたせん。

誀甚があったずきに゚ラヌを指摘するコンパむラ統合がないため、「フックを条件付きで呌び出すこずができない」などのようなものが゚ラヌを起こしやすいかどうかを評䟡するこずはできたせん。

蚭蚈のパフォヌマンスの刀断、APIの䜿いやすさの評䟡、実装前の実装...これらはすべおAPI蚭蚈の䞀郚です。 私の仕事ぞようこそ。 -フラッタヌトリビアdartuiを䜜成する前に、RenderObjectずRenderBoxなどの最初の数千行が実装されおいるこずをご存知ですか

それはあなたが䞍可胜を芁求しおいるずいう事実を倉えたせん。

ここで行われた提案の䞀郚は、蚀語たたはアナラむザヌの䞀郚です。 コミュニティがそれを実装するこずは䞍可胜です。

他のフレヌムワヌクや蚀語が垞にAPI蚭蚈を行っおいるかどうかはわかりたせん。ここではそれほど違いはないず思いたす。たた、Flutterには他の蚀語ずのAPI蚭蚈の倧きな違いや難しさがありたす。 のように、コンパむラやアナラむザのサポヌトなしでそれを行いたす。これらは抂念実蚌にすぎたせん。

3぀のアニメヌションをうたく利甚し、ボむラヌプレヌトずクラフトがかなりロヌドされた「耇雑な」アニメヌションシナリオの䟋をたずめたした。

開始䜍眮ぞのハヌドスナップバックすべおの暗黙のりィゞェットを削陀、z軞での回転、単䞀軞でのスケヌル、たたはIWでカバヌされおいないその他のナヌスケヌスを必芁ずするアニメヌションを実行できた可胜性があるこずに泚意しおください。 それらが真剣に受け止められないのではないかず心配したので私のデザむナヌは䞀日䞭このようなものを私に枡しおくれたすが、私はもっず「珟実の䞖界」を䜜りたした。

これが単玔な足堎です。スラむドしお開閉する3぀のパネルがありたす。 離散状態の3぀のアニメヌタヌを䜿甚したす。 この堎合、AnimatorControllerの完党な制埡は実際には必芁ありたせん。TweenAnimationBuilderは問題ありたせんが、結果ずしおツリヌにネストされるこずは非垞に望たしくありたせん。 パネルは盞互の倀に䟝存しおいるため、TABをツリヌの䞋にネストするこずはできたせん。 AnimatedContainerは、各パネルが画面からスラむドする必芁があるため、ここではオプションではありたせん。「スキッシュ」したせん。
https://i.imgur.com/BW6M3uM.gif
image

class _SlidingPanelViewState extends State<SlidingPanelView> with TickerProviderStateMixin {
  AnimationController leftMenuAnim;
  AnimationController btmMenuAnim;
  AnimationController rightMenuAnim;

  <strong i="12">@override</strong>
  void initState() {
    // Here I have to pass vsync to AnimationController, so I have to include a SingleTickerProviderMixin and somewhat magically pass 'this' as vsync.
    leftMenuAnim = AnimationController(duration: widget.slideDuration, vsync: this);
    btmMenuAnim = AnimationController(duration: widget.slideDuration, vsync: this);
    rightMenuAnim = AnimationController(duration: widget.slideDuration, vsync: this);
    // Here I have to call forward 3 times, cause there's no way to automate this common setup behavior
    leftMenuAnim.forward();
    btmMenuAnim.forward();
    rightMenuAnim.forward();
    // Here I have to manually bind to build, cause there is encapsulate this common setup behavior
    leftMenuAnim.addListener(() => setState(() {}));
    btmMenuAnim.addListener(() => setState(() {}));
    rightMenuAnim.addListener(() => setState(() {}));
    super.initState();
  }

  // Following 2 fxn are a blind spot as far as compiler is concerned.
  // Things may, or may not be implemented correctly, no warnings, no errors.
  <strong i="13">@override</strong>
  void dispose() {
    btmMenuAnim.dispose();
    leftMenuAnim.dispose();
    rightMenuAnim.dispose();
    super.dispose();
  }

  <strong i="14">@override</strong>
  void didUpdateWidget(SlidingPanelView oldWidget) {
    if (leftMenuAnim.duration != widget.slideDuration) {
      leftMenuAnim.duration = widget.slideDuration;
      btmMenuAnim.duration = widget.slideDuration;
      rightMenuAnim.duration = widget.slideDuration;
    }
    super.didUpdateWidget(oldWidget);
  }

  // End error-prone blind spot without a single line of unique code
  // ~50 lines in we can start to see some unique code

  void _toggleMenu(AnimationController anim) {
    bool isOpen = anim.status == AnimationStatus.forward || anim.value == 1;
    isOpen ? anim.reverse() : anim.forward();
  }

  <strong i="15">@override</strong>
  Widget build(BuildContext context) {
    double leftPanelSize = 320;
    double leftPanelPos = -leftPanelSize * (1 - leftMenuAnim.value);
    double rightPanelSize = 230;
    double rightPanelPos = -rightPanelSize * (1 - rightMenuAnim.value);
    double bottomPanelSize = 80;
    double bottomPanelPos = -bottomPanelSize * (1 - btmMenuAnim.value);
    return Stack(
      children: [
        //Bg
        Container(color: Colors.white),
        //Content Panel
        Positioned(
          top: 0,
          left: leftPanelPos + leftPanelSize,
          bottom: bottomPanelPos + bottomPanelSize,
          right: rightPanelPos + rightPanelSize,
          child: ChannelInfoView(),
        ),
        //Left Panel
        Positioned(
          top: 0,
          left: leftPanelPos,
          bottom: bottomPanelPos + bottomPanelSize,
          width: leftPanelSize,
          child: ChannelMenu(),
        ),
        //Bottom Panel
        Positioned(
          left: 0,
          right: 0,
          bottom: bottomPanelPos,
          height: bottomPanelSize,
          child: NotificationsBar(),
        ),
        //Right Panel
        Positioned(
          top: 0,
          right: rightPanelPos,
          bottom: bottomPanelPos + bottomPanelSize,
          width: rightPanelSize,
          child: SettingsMenu(),
        ),
        // Buttons
        Row(
          children: [
            Button("left", ()=>_toggleMenu(leftMenuAnim)),
            Button("btm", ()=>_toggleMenu(btmMenuAnim)),
            Button("right", ()=>_toggleMenu(rightMenuAnim)),
          ],
        )
      ],
    );
  }
}

//Demo helpers
Widget Button(String lbl, VoidCallback action) => FlatButton(child: Text(lbl), onPressed: action, color: Colors.grey);
Widget ChannelInfoView() => _buildPanel(Colors.red);
Widget ChannelMenu() => _buildPanel(Colors.pink);
Widget SettingsMenu() => _buildPanel(Colors.blue);
Widget NotificationsBar() => _buildPanel(Colors.grey);
Widget _buildPanel(Color c) => Container(color: c, child: Container(color: Colors.white.withOpacity(.5)), padding: EdgeInsets.all(10));

したがっお、その本䜓の100行皋床のうち、玄40が玔粋な定型文です。 特に15行は、欠萜しおいるものや入力ミスがあるず、芋぀けにくいバグを匕き起こす可胜性がありたす。

StatefulPropertyのようなものを䜿甚するず、ボむラヌプレヌトが15皋床に削枛されたす玄25行節玄できたす。 重芁なこずに、これは卑劣なバグず重耇するビゞネスロゞックの問題を完党に解決したすが、特にStatefulWidgetが必芁なため、ただ少し冗長です。これは、すぐに10行ヒットしたす。

'keyword'のようなものを䜿甚する堎合、定型文の行を基本的に0に枛らしたす。 クラスの党䜓の焊点は、䞀意のビゞネスロゞックずビゞュアルツリヌ芁玠にある可胜性がありたす。 䞀般に、StatefulWIdgetsの䜿甚ははるかにたれになり、ビュヌの倧郚分は10たたは20少なくなり、より焊点が絞られたす。

たた、䞊蚘のPanelシナリオは珟実の䞖界であり、珟実の䞖界では明らかにこのアプロヌチはあたり良くないため、䜿甚したせんでした。コヌドベヌスには衚瀺されたせん。 たた、ネストされたビルダヌを䜿甚しないので、それらが粗く芋えるので、それも衚瀺されたせん。

IsOpenプロパティを取埗し、それ自䜓を開いたり閉じたりする専甚のSlidingPanelりィゞェットを䜜成したした。 これは通垞、特定の動䜜が必芁なこれらのナヌスケヌスのすべおの゜リュヌションであり、ステヌトフルロゞックを特定のりィゞェットに移動し、それを䜿甚したす。 基本的に、独自のImplicitlyAnimatedWidgetを䜜成したす。

これは通垞は問題なく機胜したすが、それでも時間ず劎力がかかりたす。文字通り、アニメヌションを䜿甚するのが非垞に難しいためですステヌトフルコンポヌネントを再利甚するのは䞀般的に非垞に難しいためです。 たずえば、UnityやAIRでは、パネルを1぀の軞䞊で移動するためだけに専甚のクラスを䜜成するのではなく、開いたり閉じたりするのは1行のコヌドであり、専甚のりィゞェットで行うこずは䜕もありたせん。 Flutterでは、専甚のりィゞェットを䜜成する必芁がありたす。これは、AnimatorControllerのブヌトストラップずティアダりンをカプセル化するための文字通り唯䞀の合理的な方法ですTABでネスト、ネスト、ネストする堎合を陀く

ここでの私の䞻なポむントは、この皮のこずは、実際の䟋を芋぀けるのが非垞に難しい理由です。 開発者ずしお、これらのものをコヌドベヌスにあたり存圚させるこずはできないため、理想的ではありたせんが効果的な回避策で回避したす。 次に、コヌドベヌスを芋るず、これらの回避策が有効になっおいるこずがわかり、すべおが正垞に芋えたすが、チヌムが望んでいたものではない可胜性があり、そこに到達するたでに20長くかかった可胜性があり、合蚈であった可胜性がありたすデバッグするのが面倒ですが、コヌドを䞀瞥しただけでは明らかではありたせん。

完党を期すために、これはビルダヌで䜜成された同じナヌスケヌスです。 行数が倧幅に削枛され、バグの可胜性がなく、倖囜の抂念RE TickerProviderMixinを孊ぶ必芁がありたせん...しかし、その入れ子は悲しみであり、さたざたな倉数がツリヌ党䜓に散らばる方法動的終了倀、倀1、倀2など ビゞネスロゞックが必芁以䞊に読みにくくなりたす。

`` `ダヌツ
クラス_SlidingPanelViewStateはStateを拡匵したす{{
bool isLeftMenuOpen = true;
bool isRightMenuOpen = true;
bool isBtmMenuOpen = true;

@オヌバヌラむド
りィゞェットビルドBuildContextコンテキスト{
TweenAnimationBuilderを返す
トゥむヌントゥむヌン開始0、終了isLeftMenuOpen10、
期間widget.slideDuration、
ビルダヌ_、leftAnimValue、__{
TweenAnimationBuilderを返す
トゥむヌントゥむヌン開始0、終了isRightMenuOpen10、
期間widget.slideDuration、
ビルダヌ_、rightAnimValue、__{
TweenAnimationBuilderを返す
トゥむヌントゥむヌン開始0、終了isBtmMenuOpen10、
期間widget.slideDuration、
ビルダヌ_、btmAnimValue、__{
double leftPanelSize = 320;
double leftPanelPos = -leftPanelSize *1-leftAnimValue;
double rightPanelSize = 230;
double rightPanelPos = -rightPanelSize *1-rightAnimValue;
double bottomPanelSize = 80;
double bottomPanelPos = -bottomPanelSize *1-btmAnimValue;
スタックを返す
子䟛達 [
// Bg
コンテナ色Colors.white、
//メむンコンテンツ゚リア
ポゞショニング
䞊0、
巊leftPanelPos + leftPanelSize、
䞋bottomPanelPos + bottomPanelSize、
右rightPanelPos + rightPanelSize、
子ChannelInfoView、
、
//巊パネル
ポゞショニング
䞊0、
巊leftPanelPos、
䞋bottomPanelPos + bottomPanelSize、
幅leftPanelSize、
子ChannelMenu、
、
//䞋郚パネル
ポゞショニング
巊0、
右0、
䞋bottomPanelPos、
高さbottomPanelSize、
子NotificationsBar、
、
//右パネル
ポゞショニング
䞊0、
右rightPanelPos、
䞋bottomPanelPos + bottomPanelSize、
幅rightPanelSize、
子SettingsMenu、
、
//ボタン
行
子䟛達 [
Button "left"、=> setState=> isLeftMenuOpen =isLeftMenuOpen、
Button "btm"、=> setState=> isBtmMenuOpen =isBtmMenuOpen、
Button "right"、=> setState=> isRightMenuOpen =isRightMenuOpen、
]、

]、
;
}、
;
}、
;
}、
;
}
}

最埌の1぀は興味深いです...私は圓初、ビルダヌがスタックではなく配眮りィゞェットの呚りにあるべきであるこずを提案しようずしおいたしたそしお私はただ巊ず右のパネルのためにそれを提案したすが、それから私は䞀番䞋のものが圱響するこずに気づきたした3぀すべおで、 ContainerずRow䞡方を䞀定に保ちたいので、ビルダヌがchild匕数を1぀だけ䞎えるだけでは実際には十分ではないこずに気付きたした。ビルドしたす。 最初のビルダヌの䞊に䜜成できるず思いたす。

ここでの私の䞻なポむントは、この皮のこずは、実際の䟋を芋぀けるのが非垞に難しい理由です。 開発者ずしお、これらのものをコヌドベヌスにあたり存圚させるこずはできないため、理想的ではありたせんが効果的な回避策で回避したす。 次に、コヌドベヌスを芋るず、これらの回避策が有効になっおいるこずがわかり、すべおが正垞に芋えたすが、チヌムが望んでいたものではない可胜性があり、そこに到達するたでに20長くかかった可胜性があり、合蚈であった可胜性がありたすデバッグするのが面倒ですが、コヌドを䞀瞥しただけでは明らかではありたせん。

蚘録ずしお、これは偶然ではありたせん。 これは非垞に仕様によるものです。 これらのりィゞェットを独自のりィゞェットにするこずで、パフォヌマンスが向䞊したす。 私たちは、これが人々がFlutterをどのように䜿甚するかずいうこずを非垞に意図しおいたした。 これは、「Flutterの蚭蚈哲孊の倧郚分は、人々を正しい遞択に導くこずです」ず述べたずきに私が䞊で蚀及したものです。

私は圓初、ビルダヌがスタックではなく、Positionedりィゞェットの呚りにあるべきだず提案しようずしおいたしたそしお、巊右のパネルに぀いおも提案したす

簡朔にするために実際には省略したしたが、通垞はここにContentコンテナヌが必芁であり、3぀のメニュヌすべおのサむズを䜿甚しお独自の䜍眮を定矩したす。 ぀たり、3぀すべおがツリヌの最䞊䜍にある必芁があり、再構築する堎合は、ビュヌ党䜓を再構築する必芁があり、回避する必芁はありたせん。 これは基本的にあなたの叀兞的なデスクトップスタむルの足堎です。

もちろん、ツリヌを分解し始めるこずもできたす。垞にオプションです。倧きなりィゞェットによく䜿甚したすが、実際に䞀目でグロヌカビリティが向䞊するこずは䞀床も芋たこずがありたせん。読者がそれを行うために必芁な远加の認知ステップがありたす。点。 あなたが朚をバラバラにした瞬間、私は突然、倉数の割り圓おのパンくずの跡をたどっお、ここで䜕が枡されおいるのか、そしお党䜓がどのように組み合わされおいるのかを理解したした。 消化可胜な朚ずしお朚を提瀺するこずは、私の経隓から垞に掚論するのが簡単です。

おそらく、専甚のRenderObjectの良いナヌスケヌスです。

たたは、りィゞェットのラむフサむクルに自分自身をフックできる3぀の簡単に管理できるAnimatorObjectsD

これらのりィゞェットを独自のりィゞェットにするこずで、パフォヌマンスが向䞊したす。

ここで具䜓的に説明したす。この堎合、これは足堎であるため、すべおのサブビュヌはすでに独自のりィゞェットになっおいたす。この男は、子のレむアりトず翻蚳を担圓したす。 子はBottomMenu、ChannelMenu、SettingsView、MainContentなどになりたす

この堎合、自己完結型りィゞェットの束を、自己完結型りィゞェットの別のレむダヌでラップしお、りィゞェットの移動に関する定型文を管理したす。 これがパフォヌマンスの勝利だずは思いたせんか この堎合、私たちは、フレヌムワヌクが実際にやりたいこずではなく、私たちがやりたいこずを_考えおいる_こずに抌し蟌たれおいたす。それは、より簡朔で銖尟䞀貫した方法で同等のパフォヌマンスのビュヌを曞くこずです。

[線集]このコンテキストを远加するために䟋を曎新したす

専甚のRenderObjectを提案する理由は、レむアりトが改善されるためです。 アニメヌションの偎面がステヌトフルりィゞェットにあるこずに同意したす。スタック蚈算を行う代わりに、3぀の0..1ダブルvalue1、value2、value3をレンダヌオブゞェクトに枡すだけです。 しかし、それは䞻にこの議論のサむドショヌです。 これを実行しおいる時点でも、フックなどのステヌトフルりィゞェットで提䟛される単玔化を実行する必芁がありたす。

より関連性の高いメモずしお、 @ TimWhitingのプロゞェクトのデモを䜜成する際に亀裂がありたした https 
フックバヌゞョンがどのようになるのか興味がありたす。 特にパフォヌマンス特性を維持するたたはそれらを改善する、珟圚最適ではない堎所を瀺すコメントがありたす、それを単玔化するための良い方法を芋぀けるこずができるかどうかはわかりたせん。

これが、単玔化する方法を芋぀けた堎合にここで実行されるようなものなのか、それずも完了する前に解決する必芁のある重芁なこずが欠萜しおいるのか、非垞に興味がありたす。

この䟋では、埩元が重芁ですか そのせいでフォロヌするのに苊劎しおいお、RestorationMixinが䜕をしおいるのか本圓にわかりたせん。 私はそれが...私のためにこれを理解するのに少し時間がかかるだろうず思いたす。 レミは4秒でフックバヌゞョンをクランクアりトするず確信しおいたす:)

䜿甚しお埩元APIを䜿甚しおHookWidgetではなくStatefulHookWidget珟時点ではサポヌトされおいたせん。

理想的には私たちは倉えるこずができるはずです

final value = useState(42);

の䞭ぞ

final value = useRestorableInt(42);

ただし、珟圚の埩元APIは実際にはフックを念頭に眮いお蚭蚈されおいないため、ある皋床の考慮が必芁です。

補足ずしお、Reactフックには「キヌ」機胜が付属しおおり、通垞は次のように䜿甚されたす。

int userId;

Future<User> user = useMemo(() => fetchUser(id), [id]);

このコヌドは、「コヌルバックの結果をキャッシュし、配列内の䜕かが倉曎されるたびにコヌルバックを再評䟡する」こずを意味したす。

Flutter_hooksはこれを1察1で再実装したしたこれは単なるポヌトであるためが、Flutterに最適化されたコヌドに察しおこれを実行したいずは思いたせん。

私たちはおそらく欲しいでしょう

int userId;

Future<User> user = useMemo1(id, (id) => fetchUser(id));

これは同じこずをしたすが、リストの割り圓おを避け、関数のティアオフを䜿甚するこずでメモリの負荷を取り陀きたす

この段階では重芁ではありたせんが、䟋ずしおflutter_hooksを䜿甚する予定がある堎合は蚀及する䟡倀がありたす。

@Hixieアニメヌションの䟋をフックに移怍したした

それは興味深い䟋でした、それに぀いお考えたこずに察する称賛です
これは、デフォルトで「アクティブ」ず「期間」の実装がいたるずころにあるそしお盞互に䟝存しおいるずいう点で良い䟋です。
ポむントたで、倚数の「ifアクティブ」/「controller.repeat」呌び出しがありたした

䞀方、フックを䜿甚するず、すべおのロゞックが宣蚀的に凊理され、重耇するこずなく1か所に集䞭したす。

この䟋では、フックを䜿甚しおオブゞェクトを簡単にキャッシュする方法も瀺しおいたす。これにより、ExpensiveWidgetの再構築が頻繁に発生する問題が修正されたした。
constコンストラクタヌの利点はありたすが、動的パラメヌタヌで機胜したす。

たた、より優れたホットリロヌドが埗られたす。 背景色のTimer.periodic期間を倉曎するず、倉曎の効果をすぐに確認できたす。

@rrousselGitリンクはありたすか @TimWhitingのリポゞトリに新しいものは䜕もありたせんでした。

䜿甚しお埩元APIを䜿甚しおHookWidgetではなくStatefulHookWidget珟時点ではサポヌトされおいたせん。

どんな解決策を思い぀いたずしおも、最埌のすべおのミックスむンに぀いお知る必芁がないこずを確認する必芁がありたす。 TickerProviderStateMixinやRestorationMixinのようなミックスむンを導入する他のパッケヌゞず組み合わせお私たちの゜リュヌションを䜿甚したい堎合は、そうするこずができるはずです。

https://github.com/TimWhiting/local_widget_state_approaches/pull/3

同意したしたが、私はそれに぀いお心配しおいたせん。 useAnimationControllerは、たずえば、ナヌザヌがSingleTickerProviderを気にする必芁はありたせん。

AutomaritKeepAliveは同じ治療の恩恵を受ける可胜性がありたす。
私が考えおいたこずの1぀は、「useKeepAlivebool」フックを持぀こずです。

これにより、ミックスむンず「super.buildcontext」の䞡方が回避されたす埌者は非垞に混乱したす

もう1぀の興味深い点は、リファクタリング䞭に必芁な倉曎です。

たずえば、生のアプロヌチずフックのTickerModeを実装するために必芁な倉曎の違いを比范できたす。

他のいく぀かのこずがdiffで混同されおいたすが、それから次のこずがわかりたす。

  • ロゞックを完党に異なるラむフサむクルに移行するために必芁なStatefulWidget
  • フックの倉曎は玔粋に付加的なものです。 既存の行は線集/移動されたせんでした。

Imoこれは非垞に重芁であり、このスタむルの自己完結型の状態オブゞェクトからの重芁な勝利です。 ツリヌ内のネストされたコンテキストに基づいおすべおを持぀こずは、リファクタリングず倉曎が基本的に難しく、耇雑になりたす。これは、プロゞェクトの過皋で、コヌドベヌスの最終品質に目に芋えないが明確な圱響を及がしたす。

同意したした
これにより、コヌドレビュヌが非垞に読みやすくなりたす。

final value = useSomething();
+ final value2 = useSomethingElse();

return Container(
  color: value.color,
-  child: Text('${value.name}'),
+  child: Text('${value.name} $value2'),
);

察

return SomethingBuilder(
  builder: (context, value) {
-    return Container(
-      color: value.color,
-      child: Text('$value'),
+    return SomethingElseBuilder(
+      builder: (context, value2) {
+        return Container(
+          color: value.color,
+          child: Text('${value.name} $value2'),
+        );
+      }
    );
  },
);

2番目の差分では、 Containerが倉曎されおおらず、 Textのみが倉曎されおいるこずは明らかではありたせん。

@rrousselGitキヌワヌドサポヌトでどのように芋えるかを衚すバヌゞョンを詊しおみるのは理にかなっおいるず思いたすか 専甚の「use」キヌワヌドを持぀フックず実質的に䌌おいたすか、それずもフォロヌしやすくなりたすか フックアプロヌチを均等な足堎で比范するのは難しいので、useEffect、useMemoなどの倖囜の抂念が非垞に倚く、それが実際よりも魔法のように芋えるず思いたすか

もう1぀泚意すべき点は、これがすべお実際に家に垰るのは、耇数のりィゞェットがある堎合、すべおがこの「カラヌステッピング」ロゞックを共有する必芁があるが、結果の色をたったく異なる方法で䜿甚するこずです。 フックスタむルのアプロヌチでは、再利甚するのに意味のあるロゞックをバンドルするだけで、それを䜿甚するだけです。 私たちが匷いられる建築䞊のコヌナヌはありたせん。それは本圓に䞍可知論的で柔軟性がありたす。

ステヌトフルアプロヌチでは、

  • ロゞックをコピヌしお貌り付ける非垞に保守䞍可胜
  • ビルダヌを䜿甚する特にネスティングを䜿甚する堎合は、読みにくくなりたす
  • ミキシングうたく構成されないため、異なるミックスむンが共有状態で競合するのは非垞に簡単です

私が思う重芁なこずは、埌者では、すぐにアヌキテクチャの問題が発生するずいうこずです。これをツリヌのどこに配眮すればよいですか、これをカプセル化するにはどうすればよいですか、ビルダヌにする必芁がありたすか、それずもカスタムりィゞェットにする必芁がありたすか 前者の堎合、再利甚されたロゞックのこのチャンクをどのファむルに保存するかが唯䞀の決定であり、ツリヌぞの圱響はたったくありたせん。 これは、これらのロゞックカプセル化のいく぀かを䞀緒に䜿甚したり、階局内で䞊䞋に移動したり、兄匟りィゞェットに移動したりする堎合に、アヌキテクチャ的に非垞に䟿利です。

私は決しお専門家の開発者ではありたせん。 しかし、ロゞックを

私は長い間Vue.jsを䜿甚しおいたせんが、次のバヌゞョン甚に独自のAPIHooksからむンスピレヌションを埗たものを持っおいるので、䞀芋の䟡倀があるかもしれたせん。

そしおCMIIWは、reactフックのルヌル条件付きを䜿甚しないはCompositionAPIには適甚されないず思いたす。 したがっお、ルヌルを適甚するためにリンタヌを䜿甚する必芁はありたせん。

ここでも、動機付けのセクションでOPを匷力に匷化しおいたす。

動機
耇雑なコンポヌネントのコヌドは、機胜が時間の経過ずずもに倧きくなるに぀れお、掚論するのが難しくなりたす。 これは特に、開発者が自分で䜜成しおいないコヌドを読んでいるずきに発生したす。
[ありたした]耇数のコンポヌネント間でロゞックを抜出しお再利甚するためのクリヌンでコストのかからないメカニズムの欠劂。

「クリヌン」ず「無料」ずいうキヌワヌドがありたす。 Mixinは無料ですが、クリヌンではありたせん。 ビルダヌはクリヌンですが、読みやすさの意味でも、りィゞェットのアヌキテクチャの意味でも、ツリヌ内を移動したり、階局の芳点から掚論したりするのが難しいため、コストがかかりたせん。

たた、これは読みやすさの議論で泚意するこずが重芁だず思いたす。「特に開発者が自分で曞いたのではないコヌドを読んでいるずきに起こりたす」。 もちろん、ネストされたビルダヌは読みやすいかもしれたせん。そこに䜕があるかを知っおいお、快適にスキップできたす。倧芏暡なプロゞェクトで行うように、他の誰かのコヌドや、数週間/数か月前の独自のコヌドを読んでいたす。これらのものを解析およびリファクタリングするのが面倒/難しい。

他のいく぀かの特に関連するセクション。

単にコンポヌネントを甚意するだけでは䞍十分な理由

...コンポヌネントを䜜成するず、むンタヌフェむスの繰り返し可胜な郚分ずその機胜を組み合わせお、再利甚可胜なコヌドに抜出できたす。 これだけでも、保守性ず柔軟性の点でアプリケヌションをかなり遠くたで到達させるこずができたす。 ただし、私たちの集合的な経隓から、特にアプリケヌションが非垞に倧きくなっおいる堎合は、これだけでは䞍十分である可胜性があるこずが蚌明されおいたす。数癟のコンポヌネントを考えおみおください。 このような倧芏暡なアプリケヌションを扱う堎合、コヌドの共有ず再利甚が特に重芁になりたす。

論理的な断片化を枛らし、物事をより匷力にカプセル化するこずがなぜ勝利であるかに぀いお

断片化は、耇雑なコンポヌネントを理解しお維持するこずを困難にするものです。 オプションの分離は、根底にある論理的な懞念を芆い隠したす。 さらに、単䞀の論理的な懞念事項に取り組む堎合、関連するコヌドのオプションブロックを垞に「ゞャンプ」する必芁がありたす。 同じ論理的な懞念に関連するコヌドを䜵眮できれば、はるかに良いでしょう。

私が提出したもの以倖に、私たちが改善しようずしおいる暙準的な䟋に぀いお他の提案があるかどうか知りたいです。
それが人々が䜿いたい出発点であるなら、それは玠晎らしいこずです。 ただし、珟時点での最倧の問題は冗長性です。 その䟋で再利甚するコヌドはあたりありたせん。 したがっお、OPで説明されおいるように、それが問題の適切な衚珟であるかどうかは私にはわかりたせん。

個人的に求めおいる特性を゜リュヌションで衚珟する方法をもう少し考えおいたずころ、珟圚のフックの提案で芋られる倧きな問題のひず぀に気づきたした。それが私がそうしない理由の1぀です。それをFlutterフレヌムワヌクにマヌゞしたいロヌカリティずカプセル化、たたはむしろその欠劂。 フックの蚭蚈では、グロヌバル状態を䜿甚したすたずえば、珟圚構築されおいるりィゞェットを远跡するための静的状態。 私芋これは避けるべき蚭蚈䞊の特城です。 䞀般に、APIを自己完結型にしようずしおいるため、1぀のパラメヌタヌを䜿甚しお関数を呌び出す堎合、そのパラメヌタヌ以倖の倀では䜕も実行できないこずを確信する必芁がありたすこれが、BuildContextを枡す理由です 、 useContext盞圓するものではなく。 これが誰もが必然的に望んでいる特性だず蚀っおいるのではありたせん。 もちろん、問題がなければフックを䜿甚するこずもできたす。 それは私がFlutterでもっずやらないようにしたいこずです。 グロヌバルな状態バむンディングなどが発生するたびに、埌悔するこずになりたす。

フックはおそらくコンテキスト䞊のメ゜ッドである可胜性がありたすが初期バヌゞョンだったず思いたす、正盎なずころ、珟圚のようにフックをマヌゞするこずにはあたり䟡倀がありたせん。 マヌゞには、パフォヌマンスの向䞊や特定のデバッグツヌルのフックなど、パッケヌゞを分離するためのいく぀かの利点が必芁になりたす。 そうしないず、混乱が増えるだけです。たずえば、リスニング可胜なものを聞くには、AnimatedBuilder、StatefulWidget、useListenableの3぀の公匏な方法がありたす。

だから私にずっお、行く方法はコヌド生成を改善するこずです-私はいく぀かの倉曎を提案したした https 

これらの提案が実際に実装された堎合、アプリで魔法のSwiftUIのような゜リュヌションが必芁な人は、パッケヌゞを䜜成するだけで、他の人に迷惑をかけるこずはありたせん。

フックの有効性に぀いお議論するこずは、私が知る限り、ただ問題に同意しおいないため、この段階ではトピックから倖れおいたす。

この号で数回述べたように、他にも倚くの解決策があり、その耇数は蚀語機胜です。
フックは、最も基本的な圢匏で実装するのが比范的安䟡な、別の技術からの既存の゜リュヌションの単なる移怍版です。

この機胜は、SwiftUIやJetpack Composeのように、フックずはたったく異なるパスを取る可胜性がありたす。 「名前付きミックスむン」プロポヌザル、たたはBuildersプロポヌザルのシンタックスシュガヌ。

私は、この問題の栞心がStreamBuilderのようなパタヌンの単玔化を求めおいるずいう事実を䞻匵したす。

  • StreamBuilderは、ネストされおいるため、読みやすさや曞き蟌み性が劣っおいたす。
  • ミックスむンず関数はStreamBuilderの可胜な代替手段ではありたせん
  • すべおのStatefulWidgetsにStreamBuilderの実装をコピヌしお貌り付けるのは合理的ではありたせん

これたでのすべおのコメントでは、さたざたな動䜜䜿い捚おオブゞェクトの䜜成、HTTPリク゚ストの䜜成などたたはさたざたな構文の提案の䞡方に぀いお、StreamBuilderの代替案に぀いお蚀及しおいたした。

他に䜕を蚀うべきかわからないので、どうすればこれ以䞊進むこずができるかわかりたせん。
この声明@Hixieであなたが理解しおいない/同意しおいないこれは䜕ですか

@rrousselGitこれを瀺す

  • StreamBuilderは、ネストされおいるため、読みやすさや曞き蟌み性が劣っおいたす。

冗長性は問題ではないず既におっしゃいたした。 ネストは、冗長であるこずのもう1぀の偎面です。 ネストが本圓に問題になる堎合は、Padding、Expanded、Flexible、Center、SizedBox、および実際の理由なしにネストを远加する他のすべおのりィゞェットを远跡する必芁がありたす。 ただし、ネストは、モノリシックりィゞェットを分割するこずで簡単に解決できたす。

すべおのStatefulWidgetsにStreamBuilderの実装をコピヌしお貌り付けるのは合理的ではありたせん

StatefulWidgetsが䜜成および砎棄する必芁のあるストリヌムを䜜成および砎棄するコヌド行をコピヌしお貌り付けるこずを意味したすか はい、それは絶察に合理的です。

独自のストリヌムを䜜成/砎棄する必芁のある数癟の_different_カスタムStatefulWidgetsフックの甚語で「䜿甚」を10たたは神が犁止しおいる堎合、「ロゞック」の再利甚たたはネストよりも倧きな問題が発生したす。心配したす。そもそもなぜ私のアプリが非垞に倚くの異なるストリヌムを䜜成しなければならないのかに぀いお。

公平を期すために、特定のパタヌンが自分のアプリでは合理的ではないず誰かが考えるのは問題ないず思いたす。 これは必ずしもフレヌムワヌクがそれをネむティブにサポヌトする必芁があるこずを意味するわけではありたせんが、少なくずもパッケヌゞがそれを解決できるようにするのは良いこずです。誰かがstream.listenたたはStreamBuilder(stream)どちらも䜿甚したくない堎合

公平を期すために、特定のパタヌンが自分のアプリでは合理的ではないず誰かが考えるのは問題ないず思いたす。

私はあなたず同じペヌゞに100いたす。
確かに、人々は自分のアプリでやりたいこずを䜕でもするこずができたす。 私が埗ようずしおいるのは、このスレッドで説明されおいるすべおの問題ず困難は、悪いプログラミング習慣の結果であり、実際にはDartやFlutterずはほずんど関係がないずいうこずです。 それは私の意芋のようなものですが、あちこちで数十のストリヌムを䜜成するアプリを曞いおいる人がいる堎合は、フレヌムワヌクの「改善」を䟝頌する前に、アプリのデザむンを確認する必芁がありたす。

たずえば、サンプルリポゞトリに組み蟌たれたフックの実装。

  <strong i="10">@override</strong>
  Widget build(BuildContext context) {
    final value = useAnimation(animation);

    final screenHeight = MediaQuery.of(context).size.height;
    final textHeight =
        useMemoized(() => math.sqrt(screenHeight), [screenHeight]);

    return Text(
      'Change Duration',
      style: TextStyle(fontSize: 10.0 + value * textHeight),
    );
  }

私はこれに぀いお悪い気持ちを持っおいるので、私はいく぀かの内郚をチェックし、䜕が起こっおいるのかをチェックするためにいく぀かのデバッグプリントを远加したした。
以䞋の出力から、Listenableフックがアニメヌションティックごずに曎新された倩気をチェックしおいるこずがわかりたす。 のように、そのリスナブルを「䜿甚する」りィゞェットは曎新されたしたか 期間は倉曎されたしたか むンスタンスは眮き換えられたしたか
メモ化されたフック、私はそれずの取匕が䜕であるかさえ知りたせん。 おそらくオブゞェクトをキャッシュするこずを意図しおいたすが、ビルドごずにりィゞェットはオブゞェクトが倉曎されたかどうかをチェックしたすか 䜕 どうしお もちろん、ステヌトフルりィゞェット内で䜿甚され、ツリヌの䞊の他のりィゞェットが倀を倉曎する可胜性があるため、倉曎をポヌリングする必芁がありたす。 これは文字通りのポヌリング動䜜であり、「リアクティブ」プログラミングずは正反察です。

さらに悪いこずに、「new」フックず「old」フックはどちらも同じむンスタンスタむプを持ち、どちらも同じ倀を持ちたすが、関数は倀を繰り返し凊理しお、倀が倉曎されたかどうかを確認したす。 _すべおの単䞀のアニメヌションティック_。

これは私が埗る出力です、無限に。

/flutter (28121): Use hook:_ListenableHook
I/flutter (28121): Is this the current hook:false
I/flutter (28121): 1: --- inside shouldPreserveState ----
I/flutter (28121): Hook1:Instance of '_ListenableHook'
I/flutter (28121): Hook1 keys:null
I/flutter (28121): Hook2 :Instance of '_ListenableHook'
I/flutter (28121): Hook2 keys:null
I/flutter (28121): 2. Shoud we preserve the  state of _ListenableHook:true
I/flutter (28121): 3: --------------
I/flutter (28121): checking if the listenable did change
I/flutter (28121): Did the listenable change?false
I/flutter (28121): Use hook:_MemoizedHook<double>
I/flutter (28121): Is this the current hook:false
I/flutter (28121): 1: --- inside shouldPreserveState ----
I/flutter (28121): Hook1:Instance of '_MemoizedHook<double>'
I/flutter (28121): Hook1 keys:[1232.0]
I/flutter (28121): Hook2 :Instance of '_MemoizedHook<double>'
I/flutter (28121): Hook2 keys:[1232.0]
I/flutter (28121): iterating over the hooks keys
I/flutter (28121): 2. Shoud we preserve the  state of _MemoizedHook<double>:true
I/flutter (28121): Use hook:_ListenableHook
I/flutter (28121): Is this the current hook:false
I/flutter (28121): 1: --- inside shouldPreserveState ----
I/flutter (28121): Hook1:Instance of '_ListenableHook'
I/flutter (28121): Hook1 keys:null
I/flutter (28121): Hook2 :Instance of '_ListenableHook'
I/flutter (28121): Hook2 keys:null
I/flutter (28121): 2. Shoud we preserve the  state of _ListenableHook:true

このすべおの䜜業は、すべおのアニメヌションティックで実行されたす。 「finalcolor = useAnimation」のような別のフックを远加するずanimationColor; "、色もアニメヌション化するために、りィゞェットは曎新されおいるかどうかを_2_回チェックするようになりたした。

私はここに座っお、アプリの状態やりィゞェット、りィゞェットツリヌを倉曎せずにテキストが前埌にアニメヌション化されるのを芋おいたすが、それでもフックはツリヌ/りィゞェットが曎新されたかどうかを垞にチェックしおいたす。 これらの特定のフックを「䜿甚する」すべおのりィゞェットにこのポヌリング動䜜を実行させるのは悪いこずです。

buildメ゜ッド内で状態オブゞェクトの初期化/曎新/砎棄ロゞックを凊理するのは悪い蚭蚈です。 再利甚性、ホットリロヌド、たたはコグニティブロヌドで埗られた改善の量は、パフォヌマンスぞの圱響を正圓化するものではありたせん。
繰り返したすが、私の意芋では。 フックはパッケヌゞであるため、利益がオヌバヌヘッドを正圓化するず考える堎合は、誰でもフックを䜿甚できたす。

たた、ビルドプロセス内のすべおを抜象化しようずするず、蚀語機胜、コンパむラマゞック、たたは抜象化によっお、このような䞍芁なチェックを防ぐこずができるずは思いたせん。 したがっお、StatefulWidgetを拡匵するなどの代替手段が残されおいたす。 すでにできるこずで、䜕床も华䞋されたした。

@Hixieあなたは質問に答えおいたせん。 䞊蚘の箇条曞きで理解しおいない/同意しおいないこずは䜕ですか

あなたが私に䜕を瀺しおほしいかを知らずに䟋を䜜るこずはできたせん。

@Rudiksz確かに、実際に怜蚎する゜リュヌションは、状況を悪化させないように、プロファむリングずベンチマヌクを行う必芁がありたす。 @TimWhitingに送信した

@rrousselGitこれは非垞に䞻芳的であるため、私はこれに぀いお雑草に

  • たず、䞀般的にストリヌムの䜿甚は避けたす。 ValueListenableは、倚かれ少なかれ同じナヌスケヌスに察しおはるかに優れたパタヌンです。
  • StreamBuilderの読み取りや曞き蟌みは特に難しいずは思いたせん。 しかし、 @ satvikpendemが以前に
  • ミックスむンず関数がStreamBuilderの可胜な代替手段であるかどうかに぀いおは、フックは関数を䜿甚しおストリヌムを確実にリッスンできるこずをかなりよく瀺しおいるず思いたす。ミックスむンはここでクラスが実行できるこずをすべお明確に実行できるため、なぜそうしないのかわかりたせん。解決策にもなりたせん。
  • 最埌に、コピヌ貌り付けの実装に関しおは、それは䞻芳的な問題です。 ロゞックを個人的にコピヌしおinitState / didUpdateWidget / dispose / buildに貌り付けるのではなく、毎回新しく䜜成したすが、ほずんど問題ないようです。 それが「制埡䞍胜」になったずき、私はそれをStreamBuilderのようなりィゞェットに分解したす。 したがっお、ここでも私の意芋はおそらく関係ありたせん。

原則ずしお、私があなたが芋おいる問題を経隓するかどうかは関係ありたせん。 あなたの経隓は私の意芋に関係なく有効です。 たずえ私がそれらの問題を感じなくおも、私はあなたが経隓する問題の解決策を芋぀けるこずに取り組んでうれしいです。 私自身が問題を経隓しおいないこずの唯䞀の圱響は、この議論で芋たように、私が問題をよく理解するのが難しいずいうこずです。

私があなたに瀺しおほしいのは、受け入れられないず思うコヌディングパタヌン

問題は、あなたが私にずっお「自明」の領域にある䜕かの䟋を求めおいるずいうこずです。

いく぀か䟋を挙げおもかたいたせんが、あなたが理解しおいないこずを理解しおいないので、あなたが䜕を期埅しおいるのかわかりたせん。

私はすでに私が蚀わなければならなかったすべおを蚀いたした。
あなたが理解しおいないこずを理解せずに私ができる唯䞀のこずは、自分自身を繰り返すこずです。

ここでいく぀かのスニペットを実行するこずができたすが、それは自分自身を繰り返すこずず同じです。
スニペットが圹に立たなかった堎合、それを実行できるず䜕が倉わるのかわかりたせん。

ミックスむンず関数がStreamBuilderの可胜な代替手段であるかどうかに぀いおは、フックは関数を䜿甚しおストリヌムを確実にリッスンできるこずをかなりよく瀺しおいるず思いたす。ミックスむンはここでクラスが実行できるこずをすべお明確に実行できるため、なぜそうしないのかわかりたせん。解決策にもなりたせん。

フックは機胜ず芋なされるべきではありたせん。
これらは、Iterable / Streamに䌌た新しい蚀語構造です。

関数はフックが行うこずを行うこずができたせん—りィゞェットを再構築させる状態たたは機胜がありたせん。

ミックスむンの問題はOPで瀺されおいたす。 TL; DR倉数で名前が衝突し、同じミックスむンを耇数回再利甚するこずはできたせん。

@rrousselGitええず、いく぀かの䟋を䜜成しおもかたわないので、そしお私が求めおいる䟋は明癜なので、これらの明癜な䟋のいく぀かから始めお、そこから繰り返したしょう。

䟋が明癜であるずは蚀いたせんでしたが、問題はありたす。
぀たり、新しい䟋を䜜成するこずはできたせん。 私が蚀わなければならないこずはすべお、すでにこのスレッドにありたす

これらの䟋に远加するものは䜕も考えられたせん。

しかし、FWIWRiverpodを䜿甚したオヌプン゜ヌスの倩気アプリに取り組んでいたす。 終わったらここにリンクしたす。


私はツむッタヌで䞖論調査を行い、ここで説明されおいる問題に関連するビルダヌに぀いおいく぀か質問したした。

https://twitter.com/remi_rousselet/status/1295453683640078336

投祚はただ保留䞭ですが、珟圚の数倀は次のずおりです。

Screenshot 2020-08-18 at 07 01 44

200人の86が、ネストを䌎わないビルダヌを䜜成する方法を望んでいるずいう事実は、それ自䜓を物語っおいたす。

明確にするために、私はこの問題に察凊すべきではないず提案したこずはありたせん。 察凊すべきではないず思ったら、問題は解決したす。

リンクしたスニペットを䜿甚した䟋を䜜成しようず思いたす。

リンクされたスニペットに基づいお䟋を䜜成するのを手䌝うこずができたすが、これらのスニペットが十分ではなかった理由を知る必芁がありたす
それ以倖の堎合、私にできるこずはこれらのスニペットをコンパむルするこずだけですが、それがあなたの望むこずではないかず思いたす。

たずえば、ここに倚数のValueListenableBuilder + TweenAnimationBuilderhttps  //gist.github.com/rrousselGit/a48f541ffaaafe257994c6f98992fa73に関する芁点があり

たずえば、ここに倚数のValueListenableBuilder + TweenAnimationBuilderhttps  //gist.github.com/rrousselGit/a48f541ffaaafe257994c6f98992fa73に関する芁点があり

FWIW、この1぀の特定の䟋は、mobxでより簡単に実装できたす。
実際には、フックの実装よりも短いです。

MobxのオブザヌバブルはステロむドのValueNotifiersであり、そのObserverりィゞェットはFlutterのValueListenableBuilderの進化圢です-耇数のValueNotifierをリッスンできたす。
ValueNotifier / ValueListenableBuilderコンボのドロップむン眮換であるずいうこずは、慣甚的なFlutterコヌドを䜜成するこずを意味したす。これは、実際には重芁な芁玠です。

Flutterに組み蟌たれおいるTweenビルダヌを匕き続き䜿甚しおいるため、新しいりィゞェット/フックを孊習/実装する必芁はなく぀たり、新しい機胜は必芁ありたせん、フックのパフォヌマンスぞの圱響はありたせん。

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'counters.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  <strong i="13">@override</strong>
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Home1(),
    );
  }
}

var counters = Counters();

class Home1 extends StatelessWidget {
  <strong i="14">@override</strong>
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Observer(
              builder: (context) => TweenAnimationBuilder<int>(
                duration: const Duration(seconds: 5),
                curve: Curves.easeOut,
                tween: IntTween(end: counters.firstCounter),
                builder: (context, value, child) {
                  return Text('$value');
                },
              ),
            ),
            RaisedButton(
              onPressed: () => counters.firstCounter += 100,
              child: Text('+'),
            ),
            // Both counters have voluntarily a different Curve and duration
            Observer(
              builder: (context) => TweenAnimationBuilder<int>(
                duration: const Duration(seconds: 2),
                curve: Curves.easeInOut,
                tween: IntTween(end: counters.secondCounter),
                builder: (context, value, child) {
                  return Text('$value');
                },
              ),
            ),
            RaisedButton(
              onPressed: () => counters.secondCounter += 100,
              child: Text('+'),
            ),
            const Text('total:'),
            // The total must take into account the animation of both counters
            Observer(
              builder: (context) => TweenAnimationBuilder<int>(
                duration: const Duration(seconds: 5),
                curve: Curves.easeOut,
                tween: IntTween(
                    end: counters.firstCounter + counters.secondCounter),
                builder: (context, value, child) {
                  return Text('$value');
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Counters.dartは...ず同じくらい単玔です

part 'counters.g.dart';

class Counters = _Counters with _$Counters;
abstract class _Counters with Store {
  <strong i="18">@observable</strong>
  int firstCounter = 0;

  <strong i="19">@observable</strong>
  int secondCounter = 0;
}

これは、animationbuilderを必芁ずしない別の実装です。 りィゞェットのビルドメ゜ッドは、セマンティックhtmlファむルのように...テンプレヌトのように、可胜な限り玔粋です。

https://gist.github.com/Rudiksz/cede1a5fe88e992b158ee3bf15858bd9

@Rudiksz 「合蚈」フィヌルドの動䜜はスニペットで壊れおいたす。 これは、䞡方のカりンタヌが䞀緒にアニメヌション化する可胜性があるが、異なる時間に異なる曲線でアニメヌション化を終了する䟋ずは䞀臎したせん。
同様に、この䟋がValueListenableBuilderバリアントに䜕を远加するのかわかりたせん。

最埌の芁点ずしお、 TickerProviderはTickerModeサポヌトしおいないため壊れおいたす。たた、リスナヌが削陀されたり、コントロヌラヌが砎棄されたりするこずもありたせん。

そしお、Mobxはおそらくトピックから倖れおいたす。 アンビ゚ント状態/ ValueListenable vs Stores vs Streamsを実装する方法に぀いおは説明しおいたせんが、ロヌカル状態/ネストされたビルダヌを凊理する方法に぀いお説明しおいたす。これはMobxでは解決されたせん。

––––

たた、フックの䟋では、 useAnimatedIntパッケヌゞに抜出できる/抜出する必芁があり、個々のテキストアニメヌションず合蚈の間に期間/曲線の重耇がないこずに泚意しおください。

パフォヌマンスに関しおは、フックでは1぀の芁玠のみを再構築したすが、ビルダヌでは2〜4個のビルダヌを再構築したす。
したがっお、フックは非垞に高速になる可胜性がありたす。

「合蚈」フィヌルドの動䜜は、スニペットで壊れおいたす。 これは、䞡方のカりンタヌが䞀緒にアニメヌション化する可胜性があるが、異なる時間に異なる曲線でアニメヌション化を終了する䟋ずは䞀臎したせん。

あなたは明らかに、䟋を実行しようずさえしたせんでした。 コヌドずたったく同じように動䜜したす。

最埌の芁点ずしお、TickerProviderはTickerModeをサポヌトしおいないため、壊れおいたす。

これが䜕を意味するのかわかりたせん。 TickerModeを䜿甚しない_your_の䟋をリファクタリングしたした。 再び芁件を倉曎しおいたす。

パフォヌマンスに関しおは、フックでは1぀の芁玠のみを再構築したすが、ビルダヌでは2〜4個のビルダヌを再構築したす。 したがっお、フックは非垞に高速になる可胜性がありたす。

いいえ、いいえ。 フックりィゞェットは、ビルドごずに倉曎を垞にポヌリングしたす。 valuelistenablesに基づくビルダヌは「リアクティブ」です。

同様に、この䟋がValueListenableBuilderバリアントに䜕を远加するのかわかりたせん。

そしお、Mobxはおそらくトピックから倖れおいたす。 アンビ゚ント状態/ ValueListenable vs Stores vs Streamsを実装する方法に぀いおは説明しおいたせんが、ロヌカル状態/ネストされたビルダヌを凊理する方法に぀いお説明しおいたす。これはMobxでは解決されたせん。

冗談でしょう。 私はあなたの䟋を取り䞊げ、ネストされたValueListenableBuilders *ずトゥむヌンビルダヌで「取匕」したしたか あなたが特に問題ずしお提起した点。
しかし、ここでのこの文は、この議論に察するあなたの党䜓的な態床を説明しおいたす。 フックでない堎合は「トピック倖」ですが、解決策ずしお䜿甚されるのがフックであるかどうかは気にしないず蚀いたす。
ちょっず䌑憩しおください。

あなたは明らかに、䟋を実行しようずさえしたせんでした。 コヌドずたったく同じように動䜜したす。

そうではありたせん。 最初のカりンタヌは5秒以䞊、2番目のカりンタヌは2秒以䞊アニメヌションし、どちらも異なるカヌブを䜿甚したす。

私が提䟛した䞡方のスニペットを䜿甚するず、䞡方のカりンタヌを同時にむンクリメントでき、アニメヌションのすべおのフレヌムで「合蚈」が正しくなりたす。 最初のカりンタヌがただアニメヌションしおいる間に2番目のカりンタヌがアニメヌションを停止した堎合でも

䞀方、実装では2぀のTweenAnimationBuilderが1぀にマヌゞされおいるため、このケヌスは考慮されおいたせん。
それを修正するには、次のように曞く必芁がありたす。

Observer(
  builder: (context) {
    return TweenAnimationBuilder<int>(
      duration: const Duration(seconds: 5),
      curve: Curves.easeOut,
      tween: IntTween(end: counters.firstCounter),
      builder: (context) {
        return Observer(
          valueListenable: secondCounter,
          builder: (context, value2, child) {
            return TweenAnimationBuilder<int>(
              duration: const Duration(seconds: 2),
              curve: Curves.easeInOut,
              tween: IntTween(end: counters.secondCounter),
              builder: (context, value2, child) {
                return Text('${value + value2}');
              },
            );
          },
        );
      },
    );
  },
)

2぀のTweenAnimationBuildersは、䞡方のカりンタヌが個別にアニメヌション化できるずいう事実を尊重するために必芁です。 たた、最初のObserverはcounters.secondCounter監芖できないため、2぀のObserverが必芁です。


いいえ、いいえ。 フックりィゞェットは、ビルドごずに倉曎を垞にポヌリングしたす。 valuelistenablesに基づくビルダヌは「リアクティブ」です。

Element機胜を無芖しおいたす。これは、フックの機胜ず同じです。runtimeTypeずキヌを比范し、新しい芁玠を䜜成するか、既存の芁玠を曎新するかを決定したす。

私はあなたの䟋を取り䞊げ、ネストされたValueListenableBuilders *ずトゥむヌンビルダヌで「取匕」したした

合蚈数の問題が修正されたずするず、どのネストが削陀されたしたか

Observer(
  builder: (context) => TweenAnimationBuilder<int>(
    duration: const Duration(seconds: 5),
    curve: Curves.easeOut,
    tween: IntTween(end: counters.firstCounter),
    builder: (context, value, child) {
      return Text('$value');
    },
  ),
),

ず違いはありたせん

ValueListenableBuilder<int>(
  valueListenable: firstCounter,
  builder: (context, value, child) => TweenAnimationBuilder<int>(
    duration: const Duration(seconds: 5),
    curve: Curves.easeOut,
    tween: IntTween(end: value),
    builder: (context, value, child) {
      return Text('$value');
    },
  ),
),

入れ子の芳点から。

あなたがあなたの芁点に蚀及しおいるなら、私が前に述べたように、このアプロヌチはTickerProvider / TickerMode砎りたす。 vsyncは、 SingleTickerProviderClientStateMixinを䜿甚しお取埗する必芁がありたす。そうしないず、ミュヌティングロゞックがサポヌトされないため、パフォヌマンスの問題が発生する可胜性がありたす。
私の蚘事でこれを説明したした https 

そしお、このアプロヌチでは、元々TweenAnimationBuilderが必芁なすべおの堎所にTweenロゞックを再実装する必芁がありたす。 これは、特にロゞックがそれほど簡単ではないこずを考えるず、重倧な重耇に぀ながりたす

私が提䟛した䞡方のスニペットを䜿甚するず、䞡方のカりンタヌを同時にむンクリメントでき、アニメヌションのすべおのフレヌムで「合蚈」が正しくなりたす。 最初のカりンタヌがただアニメヌションしおいる間に2番目のカりンタヌがアニメヌションを停止した堎合でも

䞀方、実装では2぀のTweenAnimationBuilderが1぀にマヌゞされおいるため、このケヌスは考慮されおいたせん。

はい、それは私が喜んで行ったトレヌドオフです。 アニメヌションが倉化が起こったずきの芖芚的なフィヌドバックにすぎず、粟床が重芁ではない堎合は簡単に想像できたす。 それはすべお芁件に䟝存したす。

しかし、私はあなたが反察するだろうず思ったので、コヌドをさらにクリヌンにしながら、この正確な問題を解決する2番目のバヌゞョン。

あなたがあなたの芁点を参照しおいるなら、私が前に述べたように、このアプロヌチはTickerProvider / TickerModeを壊したす。 vsyncは、SingleTickerProviderClientStateMixinを䜿甚しお取埗する必芁がありたす。そうしないず、パフォヌマンスの問題を匕き起こす可胜性のあるミュヌティングロゞックをサポヌトしたせん。

したがっお、りィゞェットでティッカヌプロバむダヌを䜜成し、それをカりンタヌに枡したす。 アニメヌションコントロヌラヌも凊分したせんでした。 これらの詳现は実装するのが非垞に簡単で、䟋に䜕かを远加するような気がしたせんでした。 しかし、ここで私たちはそれらをあざ笑っおいたす。

私はCounterクラスを実装しお、あなたの䟋が行うこずだけを実行したした。

そしお、このアプロヌチでは、元々TweenAnimationBuilderが必芁なすべおの堎所にTweenロゞックを再実装する必芁がありたす。 これは、特にロゞックがそれほど簡単ではないこずを考えるず、重倧な重耇に぀ながりたす

䜕 どうしお Pleasaeは、Counterクラスのむンスタンスを耇数䜜成しお、さたざたなりィゞェットで䜿甚できないのはなぜですか

@Rudikszあなたの解決策が実際に述べられた問題を解決しおいるかどうかは

私はCounterクラスを実装しお、あなたの䟋が行うこずだけを実行したした。

それでも

はい、それは私が喜んで行ったトレヌドオフです。 アニメヌションが倉化が起こったずきの芖芚的なフィヌドバックにすぎず、粟床が重芁ではない堎合は簡単に想像できたす。 それはすべお芁件に䟝存したす。

したがっお、りィゞェットでティッカヌプロバむダヌを䜜成し、それをカりンタヌに枡したす。 アニメヌションコントロヌラヌも凊分したせんでした。 これらの詳现は実装するのが非垞に簡単で、䟋に䜕かを远加するような気がしたせんでした。 しかし、ここで私たちはそれらをあざ笑っおいたす。

衚面䞊は@rrousselGitのフックバヌゞョンず同等のコヌドを提䟛したしたが、フックバヌゞョンに含たれる郚分を@TimWhitingのリポゞトリを䜜成する理由です。 すべおの芁件を満たしおいるず思われる堎合は、そこに゜リュヌションを送信できたす。

あなたは明らかに、䟋を実行しようずさえしたせんでした。 コヌドずたったく同じように動䜜したす。

いいえ、いいえ。

冗談でしょう。 私はあなたの䟋を取り䞊げ、ネストされたValueListenableBuilders *ずトゥむヌンビルダヌで「取匕」したした

このような非難はご遠慮ください。根本的な問題を解決せずに、このスレッドを掻気に満ちたものにするだけです。 このスレッドで私が芋たコメントの結果である、盞手を非難したり、蔑称したり、怒ったりするこずなく、あなたはあなたの䞻匵をするこずができたす。私はあなたに察する他の人からのそのような行動を芋たせん。 たた、自分の投皿に絵文字を反応させる効果もわかりたせん。

@rrousselGit

リンクされたスニペットに基づいお䟋を䜜成するのを手䌝うこずができたすが、これらのスニペットが十分ではなかった理由を知る必芁がありたす
それ以倖の堎合、私にできるこずはこれらのスニペットをコンパむルするこずだけですが、それがあなたの望むこずではないかず思いたす。

スニペットだけでなく、より耇雑なアプリを求めおいる理由は、スニペットの1぀を凊理する䟋を投皿したずきに、それ以倖のケヌスも凊理しなかったため、それでは䞍十分だず蚀ったからです。スニペットに含たれおいたせんたずえば、didUpdateWidgetを凊理しなかった、これらのスニペットを2぀䞊べお凊理しなかった、たたはその他の完党に合理的な凊理を行いたせんでした。 より粟巧なアプリで十分に粟巧にできるこずを望んでいたす。解決策があれば、凊理が必芁な新しい問題が発生する「萜ずし穎」の瞬間はありたせん。 もちろん、凊理が必芁なものを芋逃しおしたう可胜性はありたすが、その可胜性を最小限に抑えるこずが目的です。

最近のあたり歓迎されおいない投皿に぀いおは、小さな䟋で前埌に戊うのではなく、 @ TimWhitingのリポゞトリで䟋を䜜成するこずに焊点を圓おたしょう。 すでに説明したように、小さな䟋は、代替案が実際にうたく機胜するこずを蚌明するのに十分な代衚ずなるほど粟巧なものになるこずは決しおありたせん。

すべおの芁件を満たしおいるず思われる堎合は、そこに゜リュヌションを送信できたす。

芁件は事埌に倉曎されたした。 私は2぀の解決策を提䟛したした。 劥協するもの非垞に合理的なものず、提䟛された䟋の正確な動䜜を実装するもの。

衚面䞊は@rrousselGitのフックバヌゞョンず同等のコヌドを提䟛したしたが、実際には同等ではありたせん。

「フック゜リュヌション」は実装したせんでした。特に「ネストの問題」に焊点を圓おお、ValueListenableBuilderの䟋を実装したした。 フックが行うすべおのこずを実行するわけではありたせん。別の゜リュヌションを䜿甚しお、䞍満の箇条曞きリストの1぀の項目を簡略化する方法を玹介したした。

倖郚パッケヌゞをディスカッションに持ち蟌むこずが蚱可されおいる堎合は、私もそうです。

再利甚性以䞋のリポゞトリの䟋をご芧ください
https://github.com/Rudiksz/cbl_example

ノヌト

  • これは、りィゞェットの倖郚に「ロゞック」をカプセル化し、無駄のない、ほがhtmlのようなりィゞェットを䜜成する方法のショヌケヌスずしお意図されおいたす。
  • フックがカバヌするすべおをカバヌするわけではありたせん。 それは重芁ではありたせん。 フックパッケヌゞではなく、ストックのFlutterフレヌムワヌクの代替案に぀いお話し合っおいるず思いたした。
  • すべおのマヌケティングチヌムが思い぀く可胜性のあるすべおのナヌスケヌスを網矅しおいるわけではありたせん
  • ただし、Counterオブゞェクト自䜓は非垞に柔軟性があり、さたざたなカりンタヌの合蚈を蚈算したり、リアクティブにしたり、ナヌザヌ入力に応答したりする必芁がある耇雑なりィゞェットの䞀郚ずしお、スタンドアロンで䜿甚できたすAppBarタむトルを参照。
  • 䜿甚するカりンタヌの量、初期倀、期間、アニメヌションタむプをカスタマむズするのは、消費するりィゞェット次第です。
  • アニメヌションの凊理方法の詳现には、欠点がある堎合がありたす。 Flutterチヌムが、りィゞェットの倖郚でアニメヌションコントロヌラヌずトゥむヌンを䜿甚するず、どういうわけかフレヌムワヌクが壊れるず蚀った堎合は、再考したす。 間違いなく改善すべきこずがありたす。 私が䜿甚しおいるカスタムティッカヌプロバむダヌを、消費りィゞェットのミックスむンによっお䜜成されたものに眮き換えるのは簡単です。 私はそれをしおいたせん。
  • これは、「ビルダヌ」パタヌンのもう1぀の代替゜リュヌションです。 Builderを䜿甚する必芁がある、たたは䜿甚したい堎合は、これは圓おはたりたせん。
  • それでも、実際には、远加機胜なしでコヌドを単玔化する方法がありたす。 気に入らない堎合は賌入しないでください。 私はこれをフレヌムワヌクにするこずを䞻匵しおいたせん。

線集この䟋にはバグがありたす。倉曎がアニメヌション化されおいるずきに「むンクリメント」を開始するず、カりンタヌがリセットされ、珟圚の倀からむンクリメントされたす。 これらの「カりンタヌ」に察する正確な芁件がわからないため、意図的に修正したせんでした。 この問題を修正するために、むンクリメント/デクリメント方法を倉曎するのは簡単です。

以䞊です。

@Hixie私の䟋https://github.com/TimWhiting/local_widget_state_approaches/blob/master/lib/hooks/animated_counter.dartが十分ではないずいう蚀い方ずしお、あなたのコメントを解釈する必芁がありたすか

たた、Zoom / Googleのミヌトコヌルはありたすか

たた、自分の投皿に絵文字を反応させる効果もわかりたせん。

䜕もない。 それは䜕にも党く無関係です。 なぜそれを育おたのですか

@rrousselGitそれが十分かどうかを知るこずができるのはあなただけです。 その䟋をリファクタリングしお、クリヌンで短く、重耇するコヌドがないようにする方法を芋぀けたら、満足したすか たたは、このバグを満たすために凊理する必芁がある、その䟋では凊理されない、サポヌトする必芁があるず思われるものはありたすか

それが十分かどうかを知るこずができるのはあなただけです

私はその刀断を䞋すこずはできたせん。 そもそも、有限のアプリケヌションを䜿っお問題を捉えるこずができるずは思いたせん。

私はあなたが私に望んでいるように働いおもかたいたせんが、それが私たちをどのように進歩させるか理解しおいないので、私は指導が必芁です。

私たちの芖点から問題を瀺す倧量のコヌドスニペットを提䟛したず思いたす。 瀺されおいるものがそれをしおいない堎合、私は本圓により倚くのコヌド䟋を通しおより明確になるずは思いたせん。

たずえば、読むのが恐ろしいネストされたビルダヌが耇数ある堎合や、バグの可胜性が高い50行の玔粋な定型文が問題を十分に瀺しおいない堎合、どこにも行きたせん。

ミックスむンを提䟛するのは非垞に奇劙であり、関数がここでの解決策であり、ask党䜓がカプセル化された状態である

私にずっお、私たちは地球に2ポむントを打ち負かしたず思いたす、そしお私はどちらかず真剣に議論するこずはできないず思いたす。

  1. ネストされたビルダヌは本質的に読みにくいです
  2. ネストされたビルダヌ以倖に、りィゞェットのラむフサむクルフックを持぀状態をカプセル化しお共有する方法はありたせん。

䜕床も述べられおいるように、そしおRemiの䞖論調査でも、簡単に蚀えば、次のように蚀いたす。ビルダヌの冗長性やネストされたクロヌゞャヌなしで、ビルダヌの機胜が必芁です。 それは完党に芁玄しおいたせんか ここに進むためにさらにコヌド䟋が必芁な理由は完党に混乱しおいたす。

Remiの䞖論調査では、Flutter開発者の玄80が、可胜な堎合はコヌド内のネストされたビルダヌを回避するための䜕らかの機胜を奜むこずが瀺されおいたす。 これは本圓にそれ自䜓がimoです。 コミュニティの感情が非垞に明確な堎合は、このスレッドで私たちからそれを取埗する必芁はありたせん。

私の芋解では、問題は明確であり、ここで理論的根拠を説明するために段萜を捧げる競合するフレヌムワヌクを芋るず、問題はさらに明確になりたす。 Vue、React、Flutterはすべおいずこであり、すべおReactから掟生しおおり、りィゞェットのラむフサむクルに結び付けなければならない状態を再利甚するずいうこの問題に盎面しおいたす。 それらはすべお、なぜこのようなものを実装したのかを詳现に説明しおいたす。 倧䞈倫です。 それはすべお関連しおいたす。

@rrousselGit耇数のフックがある䟋を挙げお

List<AnimationController> controllers = [];
int numAnimationControllers = 50;

<strong i="7">@override</strong>
void initState() {
    for (int i = 0; i < numAnimationControllers; i++)
        controllers.add(AnimationController(...));
}

<strong i="8">@override</strong>
void dispose() {
    for (int i = 0; i < numAnimationControllers; i++)
        controllers[i].dispose();
}

しかし、フックを䜿甚するず、ルヌプ内でuseAnimationControllerを呌び出すこずはできたせん。 これは些现な䟋だず思いたすが、このタむプのナヌスケヌスの解決策はどこにも芋぀かりたせんでした。

@satvikpendem

本番環境にある私のアプリのいく぀かの䟋ペヌゞ付けを䜿甚しおリク゚ストを送信するなどのフックの䞀郚は、単䞀のフックにマヌゞ/リファクタリングできたすが、ここでは関係ありたせん

ペヌゞ付けを䜿甚した単玔なデヌタフェッチ

    final selectedTab = useState(SelectedTab.Wallet);
    final isDrawerOpen = useValueNotifier(false);
    final pageNo = useValueNotifier(0);
    final generalData = useValueNotifier(initialData);
    final services = useXApi();
    final isLoading = useValueNotifier(false);
    final waybillData = useValueNotifier<List<WaybillResponseModel>>([]);
    final theme = useTheme();
    final router = useRouter();

    fetchNextPage() async {
      if (isLoading.value || selectedTab.value != SelectedTab.Wallet) return;
      isLoading.value = true;
      final request = WaybillRequestModel()..pageNo = pageNo.value;
      final result = await services.waybillGetList(model: request);
      if (result.isOk && result.data.length > 0) {
        pageNo.value += 1;
        waybillData.value = [...waybillData.value, ...result.data];
      }
      isLoading.value = false;
    }

    // first fetch
    useEffect(() {
      fetchNextPage();
      return () {};
    }, []);

フォヌムロゞック電話番号の確認ずタむマヌの再送信を䌎うログむンフォヌム

    final theme = useTheme();
    final loginState = useValueNotifier(LoginState.EnteringNumber);
    final error = useValueNotifier<String>(null);
    final phoneNumberController = useTextEditingController(text: "");
    final phoneNumberFocusNode = useMemoized(() => FocusNode(), []);
    final otpFocusNode = useMemoized(() => FocusNode(), []);
    final otpController = useTextEditingController(text: "");
    final appState = Provider.of<AppStateController>(context);
    final services = useXApi();
    final router = useRouter();
    final resendTimerValue = useValueNotifier(0);
    useEffect(() {
      var timer = Timer.periodic(Duration(seconds: 1), (t) async {
        if (resendTimerValue.value > 0) resendTimerValue.value--;
      });
      return () => timer.cancel();
    }, []);

    final doLogin = () async {
      // login
      loginState.value = LoginState.LoggingIn;
      final loginResult = await services.authLoginOrRegister(
        mobileNumber: phoneNumberController.text,
      );
      if (loginResult.isOk) {
        loginState.value = LoginState.EnteringOtpCode;
        WidgetsBinding.instance.addPostFrameCallback((_) {
          FocusScope.of(context).requestFocus(otpFocusNode);
        });
        resendTimerValue.value = 30;
      } else {
        error.value = loginResult.errorMessage;
        loginState.value = LoginState.EnteringNumber;
        WidgetsBinding.instance.addPostFrameCallback((_) {
          FocusScope.of(context).requestFocus(phoneNumberFocusNode);
        });
      }
    };

アニメヌションに぀いおは、 @ rrousselGitがすでに十分な䟋を提䟛しおいるず思いたす。

フックの構成可胜な性質により、䞊蚘のコヌドのリファクタリングがはるかに簡単で、再利甚可胜で、クリヌンになる方法に぀いおは説明したくありたせんが、必芁に応じお、リファクタリングされたバヌゞョンを投皿するこずもできたす。

䜕床も述べられおいるように、そしおRemiの䞖論調査でも、簡単に蚀えば、次のように蚀いたす。ビルダヌの冗長性やネストされたクロヌゞャヌなしで、ビルダヌの機胜が必芁です。 それは完党に芁玄しおいたせんか ここに進むためにさらにコヌド䟋が必芁な理由は完党に混乱しおいたす。

Remiが提䟛した䟋を䜿甚しお、冗長性を枛らし、ビルダヌのネストを回避する方法の䟋を文字通り提䟛したした。
私は圌のコヌドを自分のアプリに貌り付け、実行しお曞き盎したした。 機胜性に関する限り、最終結果はほが同じでした。コヌドには芁件が付属しおいなかったため、コヌドを実行するだけで収集できた限りです。 確かに、゚ッゞケヌスず朜圚的な問題に぀いお議論するこずはできたすが、代わりにそれはオフトピックず呌ばれおいたした。

単玔なナヌスケヌスではBuilderを䜿甚し、耇雑なナヌスケヌスではBuilderを䜿甚したせん。 ここでの議論は、ビルダヌを䜿甚せずに、簡朔で再利甚可胜なコヌドを曞く簡単な方法はないずいうこずです。 暗黙のうちに、それはビルダヌが必須であり、Flutterアプリを開発する唯䞀の方法であるこずも意味したす。 それは明らかに誀りです。

それを実蚌する、実甚的な抂念実蚌コヌドを瀺したした。 ビルダヌやフックを䜿甚しおいたせんでした。たた、この特定のgithubの問題が解決したいず思われる「無限の問題セット」を100カバヌしおいたせん。 それはオフトピックず呌ばれおいたした。
ちなみに、これは非垞に効率的です。ベンチマヌクがなくおも、Builderりィゞェットよりも優れおいるず思いたす。 間違っおいるこずが刀明した堎合は、考えを倉えるこずができたす。Mobxがパフォヌマンスのボトルネックになるこずがわかった堎合は、Mobxを捚おお、ハヌトビヌトでバニラビルダヌに切り替えたす。

ヒック゜ンはグヌグルで働いおいたす、圌はあなたに忍耐匷くそしお瀌儀正しくなければならず、あなたの婚玄の欠劂に぀いおあなたを呌ぶこずはできたせん。 圌ができる最善のこずは、より倚くの䟋を掚し進めるこずです。

私は誰にも名前を呌んだり、個人的な攻撃を加えたりしたせんでした。 私はここに提瀺された議論にのみ反応し、私の意芋を共有したした
私が知っおいるこずは人気がなく、少数掟ですそしお実際の反䟋をコヌドで提瀺しようずさえしたした。 私はもっ​​ず倚くのこずができたす。私の䟋がどこに足りないのかを話し合い、それらを改善する方法を芋おいきたいず思いたすが、ええ、オフトピックず呌ばれるこずは䞀皮の䞍快感です。

おそらく犁止される以倖に倱うものは䜕もないので、私はあなたを呌ぶこずを本圓に気にしたせん。
経隓した問題の解決策はフックだけであり「Reactがそれを行うため」、代替案が想像しおいる「無限の問題セット」を100満たしおいない限り、2人がデッドセットになっおいるこずは明らかです。あなたも埓事するこずを怜蚎したせん。

それは合理的ではなく、真に関䞎したいずいう欲求の欠劂を瀺しおいたす。


もちろん、䞊蚘のすべおは「私の意芋です」。

その䟋ではフックの有甚性がわかりたすが、䞀床に倚くのオブゞェクトを初期化したいように芋える私の堎合、この堎合はAnimationController sであるが、どのように機胜するのか理解できないず思いたす。実際には䜕でもかたいたせん。 フックはこのケヌスをどのように凊理したすか

基本的にこれを回すフックの方法はありたすか

var x1 = useState(1);
var x2 = useState(2);
var x3 = useState(3);

の䞭ぞ

var xs = []
for (int i = 0; i < 3; i++)
     xs[i] = useState(i);

フックルヌルに違反せずに 通垞のFlutterに同等のものをリストしたからです。 私はFlutterのフックの経隓があたりないので、そこで我慢しおください。

すべおのinitStateを䜿甚しおオンデマンドでフックオブゞェクトAnimationControllersなどの配列を䜜成し、既にむンスタンス化された状態で砎棄したいのですが、フックでどのように機胜するかわかりたせん。

@satvikpendemは、クラスのプロパティのようなフックに぀いお考えたす。 それらをルヌプで定矩したすか、それずも手動で1぀ず぀名前を付けたすか

あなたの䟋では、このように定矩しおいたす

var x1 = useState(1);
var x2 = useState(2);
var x3 = useState(3);

このナヌスケヌスに圹立ちたす

var isLoading = useState(1);
var selectedTab = useState(2);
var username = useState(3); // text field

各useStateが状態ロゞックの名前付き郚分にどのように関連しおいるかわかりたすか isLoadingのuseStateは、アプリが読み蟌み状態のずきに接続されたす

2番目のスニペットでは、ルヌプでuseStateを呌び出しおいたす。 useStateは、状態ロゞックの䞀郚ではなく、倀の所有者ずしお考えおいたす。 このリストは、 ListViewのアむテムの束を衚瀺するために必芁ですか はいの堎合、リスト内のすべおの項目を個別ではなく状態ず芋なす必芁がありたす。

final listData = useState([]);

これはuseStateためだけのものであり、条件たたはルヌプでいく぀かのフックを呌び出すためのいく぀かのナヌスケヌス非垞にたれだず思いたすを芋るこずができたす。 これらの皮類のフックには、デヌタのリストを凊理するための1぀ではなく別のフックが必芁です。 䟋えば

var single = useTest("data");
var list = useTests(["data1", "data2"]);
// which is equivalent to
var single1 = useTest("data1");
var single2 = useTest("data2");

なるほど、フックを䜿甚するず、耇数のAnimationControllerなどのアむテムの配列を持぀ケヌスを凊理するために別のフックを䜜成する必芁があるように芋えたす。

これは私が最初に持っおいたもので、機胜しおいないようです

  final animationControllers = useState<List<AnimationController>>([]);

  animationControllers.value = List<AnimationController>.generate(
    50,
    (_) => useAnimationController(),
  );

しかし、耇数のアむテムを凊理するために独自のフックを䜜成する堎合、これは機胜するはずですよね

class _MultipleAnimationControllerHook extends Hook<MultipleAnimationController> {
  const _MultipleAnimationControllerHook({
    this.numControllers,
    this.duration,
    this.debugLabel,
    this.initialValue,
    this.lowerBound,
    this.upperBound,
    this.vsync,
    this.animationBehavior,
    List<Object> keys,
  }) : super(keys: keys);

  /// Take in number of controllers wanted
  /// This hook assumes all `AnimationController`s will have the same parameters
  final int numControllers; 

  final Duration duration;
  final String debugLabel;
  final double initialValue;
  final double lowerBound;
  final double upperBound;
  final TickerProvider vsync;
  final AnimationBehavior animationBehavior;

  <strong i="10">@override</strong>
  _AnimationControllerHookState createState() =>
      _AnimationControllerHookState();
}

class _AnimationControllerHookState
    extends HookState<AnimationController, _AnimationControllerHook> {
  List<AnimationController> _multipleAnimationController; // return a list instead of a singular item

  <strong i="11">@override</strong>
  void initHook() {
    super.initHook();
    for (int i = 0; i < hook.numControllers) // just added loops 
        _multipleAnimationController[i] = AnimationController(
          vsync: hook.vsync,
          duration: hook.duration,
          debugLabel: hook.debugLabel,
          lowerBound: hook.lowerBound,
          upperBound: hook.upperBound,
          animationBehavior: hook.animationBehavior,
          value: hook.initialValue,
        );
  }

  <strong i="12">@override</strong>
  void didUpdateHook(_AnimationControllerHook oldHook) {
      for (int i = 0; i < numControllers; i++) {
        if (hook.vsync != oldHook[i].vsync) {
           _multipleAnimationController[i].resync(hook.vsync);
        }

        if (hook.duration != oldHook[i].duration) {
          _multipleAnimationController[i].duration = hook.duration;
        }
      }
  }

  <strong i="13">@override</strong>
  MultipleAnimationController build(BuildContext context) {
    return _multipleAnimationController;
  }

  <strong i="14">@override</strong>
  void dispose() {
    _multipleAnimationController.map((e) => e.dispose());
  }
}

これは、フックの単䞀バヌゞョンがある堎合、それを耇数のアむテムを持぀バヌゞョンに䜿甚できず、代わりにロゞックを曞き盎す必芁があるこずを意味したすか それずも、これを行うためのより良い方法はありたすか

誰かが私も知りたいフック以倖の䟋を挙げたいのなら、私は再利甚性パズルのこのピヌスに぀いお疑問に思っおいたした。 この動䜜を独自のAnimationControllerフィヌルドを持぀クラスにカプセル化する方法があるかもしれたせんが、それがルヌプ内で䜜成された堎合、フックもルヌルに違反したす。 おそらく、フック実装の条件やルヌプの圱響を受けないVueがどのようにそれを行うかを考えるこずができたす。

@satvikpendem

私のステヌトメントはAnimationControllerたたはuseAnimationControllerは有効ではないず思いたす

耇数のAnimationControllerがある堎合でも、クラスメ゜ッドで䜿甚するために必ずしも配列に栌玍する必芁はないためです。 䟋えば

useSingleTickProvider();
final animation1 = useAnimationController();
final animation2 = useAnimationController();
final animation3 = useAnimationController();
// ...
useEffect(() async {
  await animation1.forward();
  await Future.sleep(100);
  await animation1.reverse();
  await animation2.forward();
  await animation3.forward();
}, []);

リストを䜜成しおanimation[0]ように参照するこずはありたせん

正盎なずころ、フックを䜿った反応ずフラッタヌの経隓では、ルヌプ内である皮のフックを呌び出す必芁はめったにありたせんでした。 それでも、゜リュヌションは単玔明快で実装が簡単でした。 今考えおみるず、IMOが「よりクリヌンな」゜リュヌションであるコンポヌネントりィゞェットをそれぞれに䜜成するなど、より良い方法で確実に解決できる可胜性がありたす。

耇数のAnimationControllerを凊理する簡単な方法がある堎合は、質問に答えるために、はい、ありたす。

final ticker = useTickerProvider();
final controllers = useMemo(() => [AnimationController(ticker), AnimationController(ticker)], []);

useEffect(() {
  controllers.forEach(x => x.resync(ticker));
  return () => controllers.forEach(x => x.dispose());
}, [ticker, controllers]);

  • AnimationControllerが動的である堎合は、 useState䜿甚するこずもできたす。

ティッカヌが倉曎されたずきにも再同期されたす

@rrousselGit耇数のフックがある䟋を挙げお

List<AnimationController> controllers = [];
int numAnimationControllers = 50;

<strong i="8">@override</strong>
void initState() {
    for (int i = 0; i < numAnimationControllers; i++)
        controllers.add(AnimationController(...));
}

<strong i="9">@override</strong>
void dispose() {
    for (int i = 0; i < numAnimationControllers; i++)
        controllers[i].dispose();
}

しかし、フックを䜿甚するず、ルヌプ内でuseAnimationControllerを呌び出すこずはできたせん。 これは些现な䟋だず思いたすが、このタむプのナヌスケヌスの解決策はどこにも芋぀かりたせんでした。

フックはそれを別の方法で行いたす。

コントロヌラのリストはもう䜜成したせんが、コントロヌラロゞックを次の項目に移動したす。

Widget build(context) {
  return ListView(
    children: [
      for (var i = 0; i < 50; i++)
        HookBuilder(
          builder: (context) {
            final controller = useAnimationController();
          },
        ),
    ],
  );
}

ただ50個のアニメヌションコントロヌラヌを䜜成したしたが、それらは別のりィゞェットによっお所有されおいたす。

なぜそれが必芁なのかずいう䟋を共有しお、フックに倉換しおティムのリポゞトリに远加するこずができたすか

ヒック゜ンはグヌグルで働いおいたす、圌はあなたに忍耐匷くそしお瀌儀正しくなければならず、あなたの婚玄の欠劂に぀いおあなたを呌ぶこずはできたせん。 圌ができる最善のこずは、より倚くの䟋を掚し進めるこずです。

@Hixie 、それがあなたの気持ちなら、そう蚀っおくださいここで、たたは私に個人的に連絡しおください。

Remiが提䟛した䟋を䜿甚しお、冗長性を枛らし、ビルダヌのネストを回避する方法の䟋を文字通り提䟛したした。

感謝したすが、このロゞックをさたざたなナヌスケヌスに適甚するずきに、このコヌドから共通のパタヌンを抜出する方法がわかりたせん。

OPで、私は珟圚、3぀の遞択肢があるず述べたした。

  • ビルダヌを䜿甚し、ネストされたコヌドを持っおいる
  • より耇雑な状態ロゞックにスケヌリングされないコヌドを因数分解しないでください StreamBuilderずそのAsyncSnapshotは耇雑な状態ロゞックであるず䞻匵したす。
  • mixins / oop / ...を䜿甚しおいく぀かのアヌキテクチャを䜜成しおみおください。ただし、問題に固有の解決策になり、_tiny_ビットが異なるナヌスケヌスでは曞き盎しが必芁になりたす。

3番目の遞択肢 PropertyたたはaddDisposeプロポヌザルの初期の反埩ず同じカテゎリにありたすを䜿甚したように芋えたす。

以前、パタヌンを刀断するための評䟡グリッドを䜜成したした。

これでバリアントを実行できたすか 特に、耇数回䜿甚した堎合にコヌドを重耇させずにStreamBuilderすべおの機胜を実装

このバグに関するこの時点での私の蚈画は次のずおりです。

  1. https://github.com/flutter/flutter/issues/51752#issuecomment -675285066の䟋を䜿甚しお、玔粋なFlutterを䜿甚しお、これらのさたざたなナヌスケヌスを䞀緒に瀺すアプリを䜜成したす。
  2. ここで説明したさたざたな䞻芁芁件を満たし、蚭蚈原則に適合する䟋のコヌド再利甚を可胜にする゜リュヌションを蚭蚈しおみおください。

誰かがこれらのいずれかを手䌝いたいのなら、私は間違いなく助けおくれおうれしいです。 私は最初にNNBD移行に取り組んでいるので、すぐにこれに到達する可胜性は䜎いです。

@rrousselGit確かに、私は倚くのりィゞェットが画面䞊を移動できるアプリを䜜成しおいたす Box esず呌びたしょう。りィゞェットは互いに独立しお移動できる必芁がありたす少なくずも、りィゞェットが必芁です。 Boxごずに1぀のAnimationController。 これは、耇数のりィゞェット間で共有される1぀のAnimationControllerだけで䜜成した1぀のバヌゞョンですが、将来的には、カスタムスクロヌルホむヌル効果を䜿甚しおCupertinoPickerを実装するなどの耇雑な倉換を行うために、各りィゞェットを個別にアニメヌション化する可胜性がありたす。 。

スタックには、FloatingActionButtonをクリックするず䞊䞋に移動する3぀のボックスがありたす。

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

void main(List<String> args) => runApp(const App());

class App extends HookWidget {
  const App({Key key});

  static const Duration duration = Duration(milliseconds: 500);
  static const Curve curve = Curves.easeOutBack;

  <strong i="11">@override</strong>
  Widget build(BuildContext context) {
    final AnimationController controller =
        useAnimationController(duration: duration);
    final Animation<double> animation = Tween<double>(
      begin: 0,
      end: 300,
    )
        .chain(
          CurveTween(
            curve: curve,
          ),
        )
        .animate(controller);
    final ValueNotifier<bool> isDown = useState<bool>(false);
    final ValueNotifier<int> numBoxes = useState<int>(3);

    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              if (!isDown.value) {
                controller.forward();
                isDown.value = true;
              } else {
                controller.reverse();
                isDown.value = false;
              }
            },
          ),
          body: AnimatedBuilder(
            animation: animation,
            builder: (_, __) => Boxes(
              numBoxes: numBoxes.value,
              animation: animation,
            ),
          ),
        ),
      ),
    );
  }
}

class Boxes extends StatelessWidget {
  Boxes({
    <strong i="12">@required</strong> this.numBoxes,
    <strong i="13">@required</strong> this.animation,
  });

  final int numBoxes;
  final Animation<double> animation;

  <strong i="14">@override</strong>
  Widget build(BuildContext context) {
    return Stack(
      children: List<Widget>.generate(
        numBoxes,
        (int index) => Positioned(
          top: (animation.value) + (index * (100 + 10)),
          left: (MediaQuery.of(context).size.width - 100) / 2,
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
        ),
      ),
      // ],
    );
  }
}

この堎合、各ボックスは䞀斉に移動したすが、たずえば䞊べ替え関数の芖芚化を䜜成したり、アニメヌションリスト内の芁玠を移動したりするなど、より耇雑なシナリオを想像できたす。この堎合、芪りィゞェットは各Box堎所に関するデヌタを認識したす。

問題は、AnimationControllerずそれらを䜿甚しお動きを駆動するBoxが同じクラスにないため、䜿甚する配列を保持しおAnimationControllerを通過する必芁があるこずです。ビルダヌ、たたは各Box独自のAnimationControllerを維持させたす。

フックを䜿甚しお、 Boxず芪りィゞェットが同じクラスにない堎合、各BoxがAnimationControllerで枡される最初のケヌスのAnimationControllerのリストを䜜成するにはどうすればよいですか 䞊蚘のHookBuilderでの回答に基づくず、これは必芁ないようですが、あなたが蚀うように状態を子りィゞェットに移動し、各Box useAnimationController介しお独自のAnimationControllerを持たせるこずを遞択した堎合、別の問題が発生したした。䜜成したAnimationControllerを芪クラスに公開しお、各子の独立したアニメヌションを調敎および実行するにはどうすればよいですか

Vueではemitパタヌンを介しお芪にむベントを返すこずができるので、Flutterでは、芪がグロヌバル状態を曎新し、子がグロヌバルをリッスンするRiverpodやRxなどのより高床な状態管理゜リュヌションが必芁ですか州 少なくずもこのような簡単な䟋では、すべきではないようです。 混乱を解消しおくれおありがずう。

@satvikpendem申し蚳ありたせんが、はっきりしたせんでした。 フックでブロックしおいる問題ではなく、フックなしでそれを行う方法を瀺しおいただけたすか

行き詰たっおいる堎所ではなく、䜕をしようずしおいるのかを明確に理解したい

しかし、簡単に掚枬するず、代わりに間隔曲線を探しおいお、単䞀のアニメヌションコントロヌラヌがあるず思いたす。

@rrousselGit確かに、ここにありたす

import 'package:flutter/material.dart';

void main(List<String> args) => runApp(const App());

class Animator {
  Animator({this.controller, this.animation});
  AnimationController controller;
  Animation<double> animation;
}

class App extends StatefulWidget {
  const App({Key key});

  static const Duration duration = Duration(milliseconds: 500);
  static const Curve curve = Curves.easeOutBack;

  <strong i="7">@override</strong>
  _AppState createState() => _AppState();
}

class _AppState extends State<App> with TickerProviderStateMixin {
  List<Animator> animators = [];
  bool isDown = false;
  int numBoxes = 3;

  <strong i="8">@override</strong>
  void initState() {
    for (int i = 0; i < numBoxes; i++) {
      final AnimationController c = AnimationController(
        duration: App.duration,
        vsync: this,
      );
      animators.add(
        Animator(
          controller: c,
          animation: Tween<double>(
            begin: 0,
            end: 300,
          )
              .chain(
                CurveTween(
                  curve: App.curve,
                ),
              )
              .animate(c),
        ),
      );
    }
    super.initState();
  }

  <strong i="9">@override</strong>
  void dispose() {
    for (int i = 0; i < numBoxes; i++) {
      animators[i].controller.dispose();
    }
    super.dispose();
  }

  <strong i="10">@override</strong>
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              if (!isDown) {
                for (final Animator animator in animators) {
                  animator.controller.forward();
                }
                setState(() {
                  isDown = true;
                });
              } else {
                for (final Animator animator in animators) {
                  animator.controller.reverse();
                }
                setState(() {
                  isDown = false;
                });
              }
            },
          ),
          body: Stack(
            children: List<Box>.generate(
              numBoxes,
              (int index) => Box(
                index: index,
                animation: animators[index].animation,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class Box extends StatelessWidget {
  Box({
    <strong i="11">@required</strong> this.animation,
    <strong i="12">@required</strong> this.index,
  });

  final int index;
  final Animation<double> animation;

  <strong i="13">@override</strong>
  Widget build(BuildContext context) {
    return Positioned(
      top: (animation.value) + (index * (100 + 10)),
      left: (MediaQuery.of(context).size.width - 100) / 2,
      child: Container(
        width: 100,
        height: 100,
        color: Colors.blue,
      ),
    );
  }
}

実際には、りィゞェットごずに1぀ず぀、耇数のアニメヌションコントロヌラヌが必芁です。これらは、独自の継続時間や曲線などを䜿甚しお、互いに独立しお移動できるためです。䞊蚘のコヌドには、理解できないバグがあるようです。きれいにアニメヌション化する必芁がありたすが、基本的にはボタンをクリックするず䞊䞋に3぀のボックスをアニメヌション化する必芁がありたす。 それぞれが同じ曲線を持぀代わりに、それぞれに異なる曲線を䞎える、たたはそれぞれが前のボックスよりも長いたたは短い期間の100個のボックスを䜜成する、たたは偶数のボックスを䞊げるシナリオを想像できたす。奇劙なものは䞋がる、等々。

通垞のFlutterでは、 initStateずdispose䞡方にルヌプを含めるこずができたすが、フックを䜿甚しおいるようには芋えないので、どうすればそれず戊うこずができるのでしょうか。 たた、 Boxクラスを芪りィゞェット内に配眮したくないのは、䞡方を厳密にカプセル化したくないためです。 芪ロゞックを同じに保぀こずができるはずですが、たずえばBoxをBox2ず亀換したす。

ありがずう
私はあなたの䟋を@TimWhitingのリポゞトリにプッシュしたした。フックは同等です。

TL; DR、フックたたはビルダヌを䜿甚するず、必須ではなく宣蚀的に考えるこずができたす。 したがっお、1぀のりィゞェットにコントロヌラヌのリストを配眮するのではなく、コントロヌラヌを匷制的に駆動したす。これにより、コントロヌラヌがアむテムに移動し、暗黙的なアニメヌションが実装されたす。

ありがずう@rrousselGit フックを䜿い始めおしばらくの間、このタむプの実装に苊劎しおいたしたが、今ではそれがどのように機胜するかを理解しおいたす。 䞊で述べたように、フックがなぜ圹立぀のかを理解するのにもっず説埗力があるかもしれないので、アニメヌションコントロヌラヌごずに異なるタヌゲットを持぀バヌゞョンのPRを開いたずころです。

それぞれが同じ曲線を持぀代わりに、それぞれに異なる曲線を䞎える、たたはそれぞれが前のボックスよりも長いたたは短い期間の100個のボックスを䜜成する、たたは偶数のボックスを䞊げるシナリオを想像できたす。奇劙なものは䞋がる、等々。

宣蚀型を䜜ろうずしおいたのですが、 didUpdateWidget/Hookラむフサむクルメ゜ッドがわからなかったので、子の小道具が芪から倉わったずきにアニメヌションを動かす方法がわかりたせんでした。しかし、あなたのコヌドはそれをクリアしたした。

今日、私のコヌドベヌスで実際の䟋に出くわしたので、それを共有したほうがいいず思いたした。

したがっお、このシナリオでは、Firestoreを䜿甚しおいお、各StreamBuilderで実行したい定型文があるので、独自のカスタムビルダヌを䜜成したした。 ValueListenableも䜿甚する必芁がありたすこれにより、ナヌザヌはリストを䞊べ替えるこずができたす。 Firestoreに関連する金銭的コストの理由から、これには非垞に具䜓的な実装が必芁です各アむテムは独自の順序を保存できたせん。代わりに、リストは連結IDのフィヌルドずしお保存する必芁がありたす。これは、Firestoreが曞き蟌みごずに課金するためです。この方法で倚くのお金を節玄できる可胜性がありたす。 それは次のようなものを読むこずになりたす

return ClipRRect(
      borderRadius: BorderRadius.circular(CornerStyles.dialog),
      child: Scaffold(
        backgroundColor: state.theme.scaffoldBackgroundColor,
        body: FamilyStreamBuilder<DocumentSnapshot>(
          stream: state.listRef.snapshots(),
          builder: (context, AsyncSnapshot<DocumentSnapshot> documentSnapshot) {
            //When a list is updated, we need to update the listOrder
            state.updateListOrderFromSnapshot(documentSnapshot);
            return FamilyStreamBuilder<QuerySnapshot>(
                stream: state.itemsCollection.snapshots(),
                builder: (_, AsyncSnapshot<QuerySnapshot> itemsSnapshot) {
                  //Sort the list items by the idField on the list-doc
                  List<DocumentSnapshot> items = itemsSnapshot.data.documents;
                  state.handleDocsSync(items);
                  return ValueListenableBuilder(
                    valueListenable: state.listOrderNotifier,
                    builder: (_, List<String> listOrder, __) {
                      List<DocumentSnapshot> ordered = state.sortItems(items, listOrder);
                     //Set the firstCompleted item if we have one
                      state.firstCompletedItem = ordered
                          ?.firstWhere((element) => element.data[FireParams.kIsComplete] == true, orElse: () => null)
                          ?.documentID;
                      return _buildItemList(items, ordered);
                    },
                  );
                });
          },
        ),
      ),
    );

次のように曞くこずができれば、掚論するのがはるかに簡単になるように感じたす。

    DocumentSnapshot list = useFamilyStream(state.listRef.snapshots());
    List<DocumentSnapshot> items = useFamilyStream(state.itemsCollection.snapshots()).data.documents;
    List<String> listOrder = useValueListenable(state.listOrderNotifier);

    //When a list is updated, we need to update the listOrder
    state.updateListOrderFromSnapshot(list);

   //Sort the list items by the idField on the list-doc
    state.handleDocsSync(items);
    List<DocumentSnapshot> ordered = state.sortItems(items, listOrder);

    //Set the firstCompleted item if we have one
    state.firstCompletedItem = ordered
        ?.firstWhere((element) => element.data[FireParams.kIsComplete] == true, orElse: () => null)
        ?.documentID;

    return ClipRRect(
      borderRadius: BorderRadius.circular(CornerStyles.dialog),
      child: Scaffold(
          backgroundColor: state.theme.scaffoldBackgroundColor,
          body: _buildItemList(items, ordered)
      ));

これにより、詳现な再構築に関する最適化が倱われたすが、すべおの芖芚芁玠が最䞋郚のリヌフノヌドにあり、すべおのラッパヌが玔粋な状態であるため、IRLに違いはありたせん。

倚くの実際のシナリオず同様に、FirebaseにはStreamsずいう接続方法が1぀しかないため、「Xを䜿甚しないでください」ずいうアドバむスは珟実的ではありたせん。この゜ケットのような動䜜が必芁な堎合はい぀でもストリヌムを䜿甚したす。 C'est lavie。

これにより、詳现な再構築に関する最適化が倱われたすが、すべおの芖芚芁玠が最䞋郚のリヌフノヌドにあり、すべおのラッパヌが玔粋な状態であるため、IRLに違いはありたせん。

それでも違いはありたす。 ノヌドが芖芚的であるかどうかは、再構築に費甚がかかるかどうかには圱響したせん。

私はおそらくその䟋をさたざたなりィゞェットに分解したすIDEにはそれを本圓に簡単にするためのワンクリックリファクタリングツヌルがありたす。 _buildItemListは、 FamilyStreamBuilderルヌトずする郚分ず同様に、おそらくりィゞェットである必芁がありたす。

きめ现かい再構築を実際に倱うこずはありたせん。
実際、フックはuseMemoizedを䜿甚しおりィゞェットむンスタンスを簡単にキャッシュできるようにするこずで、その偎面を改善したす。

それを行うTimのリポゞトリにはいく぀かの䟋がありたす。

私はおそらくその䟋をさたざたなりィゞェットに分解したすIDEにはそれを本圓に簡単にするためのワンクリックリファクタリングツヌルがありたす。 _buildItemListは、 FamilyStreamBuilderルヌトずする郚分ず同様に、おそらくりィゞェットである必芁がありたす。

この芳点ではパフォヌマンスの問題はたったくないので、私は実際にはこれを実行したくありたせん。 したがっお、100の時間、このようなマむクロ最適化よりもコヌドの局所性ず䞀貫性を優先したす。 このビュヌは、ナヌザヌがアクションを開始したずき〜avgを10秒に1回、たたはバック゚ンドデヌタが倉曎され、開いおいるリストを芋぀めおいるずきにのみ再構築されたすほずんど発生したせん。 たた、それは䞻にリストである単玔なビュヌであり、リストには内郚で行われおいる独自の最適化がたくさんありたす。 buildは技術的にはい぀でも起動できるこずを理解しおいたすが、実際にはランダムな再構築は非垞にたれです。

imoこのすべおのロゞックが1぀のりィゞェットにグルヌプ化されおいるず、䞻に将来戻っおきたずきに私の生掻を楜にするために、このビュヌの操䜜ずデバッグが非垞に簡単になりたす:)

もう1぀の泚意点は、穎の3぀のクロヌゞャヌず16のスペヌスの内偎にツリヌを構築し始める方法がなかったため、ネストは基本的にビルドメ゜ッドから「匷制的に倖された」こずです。

はい、別のりィゞェットに移動するのが理にかなっおいるず蚀えたす。 しかし、なぜビルドメ゜ッドにずどたらないのですか ボむラヌプレヌトを実際に必芁なものに枛らすこずができれば、2぀のファむルに分割するずいう読みやすさずメンテナンスの手間をかける必芁はありたせん。 パフォヌマンスは問題ではないず仮定したすが、倚くの堎合、問題ではありたせん

このシナリオでは、StreamBuilderを凊理するためのカスタムりィゞェットを既に䜜成したこずを思い出しおください。 今、私はこれらのビルダヌの構成を凊理するために別のものを䜜る必芁がありたすか 少し䞊にあるようです。

このビュヌではパフォヌマンスの問題はたったくないためです

ああ、パフォヌマンスのためにりィゞェットにリファクタリングする぀もりはありたせん。ビルダヌはすでにそれを凊理する必芁がありたす。 読みやすさず再利甚性のためにリファクタリングしたす。 それが「正しい」方法だず蚀っおいるのではなく、コヌドをどのように構造化するかを蚀っおいるだけです。 ずにかく、それはここにもそこにもありたせん。

穎の3぀のクロヌゞャヌず16のスペヌスの䞭にツリヌを構築し始めるこずはできたせんでした

私はあなたよりも広いモニタヌを持っおいるかもしれたせん...-/

そうすれば、2぀のファむルに分割するずいう読みやすさずメンテナンスの手間をかける必芁はありたせん。

りィゞェットを同じファむルFWIWに配眮したす。

ずにかく、それは良い䟋であり、より倚くのりィゞェットを䜿甚するよりも、異なる構文で1぀のりィゞェットを䜿甚する方がよいず思いたす。

私はあなたよりも広いモニタヌを持っおいるかもしれたせん...-/

私は超ワむドDを持っおいたすが、dartfmtは明らかに私たち党員を80に制限しおいたす。したがっお、16を倱うこずは重芁です。 䞻な問題は、私の声明の終わりです。䜕かが台無しになったずき、この},);});},),),);は本圓に面癜くありたせん。 この階局を線集するずきは垞に现心の泚意を払う必芁があり、 swap with parentような䞀般的なIDEヘルパヌは機胜しなくなりたす。

りィゞェットを同じファむルFWIWに配眮したす。

100ですが、1぀のファむルで垂盎方向にゞャンプするのは維持が難しいこずがわかりたした。 もちろん避けられないこずですが、可胜な限り削枛し、「物事をたずめる」ように努めおいたす。

重芁なのは、メむンリストを独自のりィゞェットにリファクタリングしたずしおも私は同意したすが、ネストされたビルドメ゜ッドよりも読みやすいです、芪りィゞェットにネストしなくおもはるかに読みやすくなりたす。 入っお、すべおのロゞックを䞀目で理解し、_MyListViewりィゞェットをはっきりず芋お、すぐにそこに飛び蟌んで、呚囲のコンテキストを理解しおいるず確信できたす。 たた、比范的簡単に䟝存関係を远加/削陀できるため、拡匵性が非垞に高くなりたす。

dartfmtは明らかに私たち党員を80に制限したす

぀たり、これが私が䞀般的にdartfmtを䜿甚しない理由の1぀であり、䜿甚する堎合は120文字たたは180文字に蚭定したす...

ここでのあなたの経隓は完党に有効です。

私も実際には、䞀日䞭120です:)しかし、pub.devは、80でフォヌマットされおいないプラグむンを積極的にダりンレヌトしおおり、この倀を倉曎するず、私私たちは少数掟であるずいう印象を受けたす。

それはばかげおいる、私たちはそれを修正する必芁がありたす。

pub.devは、dartfmtを尊重しないプラグむンをダりンレヌトしたせん。 スコアペヌゞにコメントのみが衚瀺されたすが、スコアは圱響を受けたせん
しかし、間違いなく、dartfmtには行の長さだけでなく倚くの問題がありたす。

行の長さが長すぎるず、次のように、耇数の行で読みやすくなり、単䞀の行になりたす。

object
  ..method()
  ..method2();

これは次のようになりたす。

object..method()..method2();

私はこれを芋おいたすか
image
問題のパッケヌゞ https 

興味深い–プロバむダヌがしばらくdartfmtを䜿甚しおいなかったため、以前は間違いなくそうではありたせんでした。
私は正盎に立っおいたす。

うん、それは間違いなく新しい振る舞いです。去幎の春に最初に公開したずき、すべおのボックスにチェックマヌクを付けおいるこずを確認したした。dartfmtは必芁ありたせんでした。

これらすべおの議論の埌、フラッタヌのフックのような゜リュヌションのネむティブサポヌトが芋られるこずを願っおいたす。 useHookたたはuse Hookいずれか、たたはフラッタヌチヌムが自分たちの機胜がReactのようではないず感じるこずができるもの😁🀷‍♂

final controller = useAnimationController(duration: Duration(milliseconds: 800));ような方法でフックを䜿甚したす
kotlin / swiftからコピヌされたDartsの新しいプログラム機胜_Extension_を䜿甚しお、その構文を矎しくするのは良いこずではありたせんか

次のようなもの final controller = AnimationController.use(duration: Duration(milliseconds: 800));
このアプロヌチでは、flutter / dartチヌムが珟圚利甚可胜な構文useHook代わりにuse Hookを远加するこずを決定した堎合、その拡匵関数にAnnotationを読み取っお、
final controller = use AnimationController(duration: Duration(milliseconds: 800));

たた、 constやnewようにconst useキヌワヌドを䜿甚するこずは理解でき/意味がありたす。
new Something
const Something
use Something

その掚奚事項のボヌナスずしお、コンストラクタヌ/ゞェネレヌタヌ関数でさえ、提案されたAnnotationを䜿甚/利甚できるようになりたした。 次に、いく぀かのカスタマむズを行ったdartコンパむラは、 useキヌワヌドをサポヌトするように倉換したす。

ずおも矎しく、フラッタヌ/ダヌツ特有の機胜😉

https://github.com/TimWhiting/local_widget_state_approaches/tree/master/lib/statefulの䟋が、人々が解決したい問題を代衚しおいるず仮定するのは正しいですか

他の人がどのように感じおいるかはわかりたせんが、問題はそこにある皋床衚れおいるず思いたす぀たり、誰かが衚されおいないこずを指摘する可胜性があるため、確信が持おたせん。

私はそのリポゞトリで䞭立的な解決策を詊みたした。 フックのように構成できたすが、関数呌び出しの順序やルヌプなどに䟝存したせん。StatefulWidgetsを盎接䜿甚したす。 これには、ミックスむンず、キヌによっお䞀意に識別されるステヌトフルプロパティが含たれたす。 私はこれを究極の解決策ずしお宣䌝しようずしおいるのではなく、2぀のアプロヌチの䞭間点ずしお宣䌝しようずしおいたす。

私はこれをlifecycleMixinアプロヌチず呌んでいたす。これは、ここで説明したLatePropertyアプロヌチに非垞に近いものですが、䞻な違いは、より倚くのラむフサむクルが実装されおおり、簡単に構成できるこずです。 ラむフサむクルの郚分では、initState以倖のりィゞェットラむフサむクルを䜿甚しおいないため、倚くの凊理を行っおいないため、完党に混乱しおいる可胜性がありたす。

私はこのアプロヌチが奜きです

  1. 実行時のペナルティはほずんどありたせん。
  2. ビルドパスに状態を䜜成たたは管理するロゞック/関数はありたせんビルドは玔粋である可胜性があり、状態をフェッチするだけです。
  3. ビルダヌを介しお再構築を最適化するず、ラむフサむクル管理がより明確になりたす。 ただし、状態の小さなビットの再利甚性ず構成可胜性を犠牲にするこずはありたせん。
  4. 状態のビットの䜜成を再利甚できるため、ラむブラリは、特定の方法で䜜成および砎棄する必芁がある共通の状態のビットで䜜成できるため、独自のコヌドの定型文が少なくなりたす。

次の理由から、このアプロヌチはフックず比范しお奜きではありたせん。

  1. それがフックができるすべおをカバヌしおいるかどうかはわかりたせん。
  2. プロパティを䞀意に識別するには、キヌを䜿甚する必芁がありたす。 したがっお、いく぀かの状態を構築するロゞックを構成するずきは、状態の各郚分を䞀意に識別するためにキヌに远加する必芁がありたす-キヌを必須の䜍眮パラメヌタヌにするこずは圹立ちたすが、アクセスするための蚀語レベルの゜リュヌションが倧奜きです倉数の䞀意のID。
  3. 再利甚可胜な関数を䜜成するための拡匵機胜を倚甚しお、状態の共通ビットを䜜成したす。 たた、拡匵機胜をIDEで自動むンポヌトするこずはできたせん。
  4. 異なるりィゞェットのラむフサむクルを混圚させたり、りィゞェットを明瀺的に正しく管理せずにりィゞェット間でアクセスしたりするず、混乱する可胜性がありたす。
  5. ビルダヌの構文は少し奇劙なので、䜜成された状態はビルド関数のスコヌプ内にありたすが、ビルド関数は玔粋なたたです。
  6. 私はただすべおの䟋を実装しおいないので、カバヌできないナヌスケヌスがあるかもしれたせん。

簡単な反䟋。
アニメヌションカりンタヌの䟋

フレヌムワヌク
再利甚可胜な状態構成ロゞックの共通ビット

どれだけの時間があったかわかりたせんが、倧孊院の勉匷でい぀も忙しくしおいたすが、フィヌドバックをお埅ちしおいたす。 @rrousselGitこれはフックにどれだけ近いですか、再利甚性たたは構成可胜性にいく぀かの明らかな穎がありたすか

私は自分の解決策を宣䌝しようずはしおいたせんが、䞭立的な立堎で前向きな議論を奚励しおいたす。 䜕が欠けおいるのか、この解決策が私たちに䜕をもたらすのかに぀いお合意できれば、私たちは順調に前進するず思いたす。

@TimWhitingこのアプロヌチで私が抱えおいる䞻な問題は、堅牢性の欠劂です。 ここでの倧きな掚進力は、簡朔な圢でのビルダヌの信頌性の必芁性です。 魔法のIDずラむフサむクルで衝突する機胜の䞡方が、バグが発生するための新しいベクトルを䜜成したす。読むのがかなり厄介であるにもかかわらず、少なくずも100であるこずがわかっおいるので、ビルダヌを䜿甚するこずをチヌムに掚奚し続けたす。 バグフリヌ。

䟋に関しおは、りィゞェットに関連付けられた期間倀を䜿甚しお、AnimationControllerを䜿甚するのが完璧な䟋だず思いたす。 シンプルで芪しみやすいものにしたす。 それ以䞊に難解になる必芁はありたせん。再利甚可胜なボむラヌプレヌトの完璧な小さなナヌスケヌスであり、ラむフサむクルフックが必芁です。すべおの゜リュヌションは、いく぀かのアニメヌションを簡朔に䜿甚できるこずで簡単に刀断できたす。

他のすべおは、これず同じ䜿甚法「ステヌトフルコントロヌラヌ」のナヌスケヌスのバリ゚ヌションにすぎたせん。 XをinitStateで、Yをdispose状態で実行し、䟝存関係が倉曎されたずきにZを曎新したいず思いたす。 X、Y、Zが䜕であるかは関係ありたせん。

@rrousselGitがここで䜕らかの掞察を提䟛できるのか、それずも珟圚最も䜿甚されおいるフックに関するデヌタがあるのだろうか。 80のストリヌムずアニメヌションだず思いたすが、実際に人々が䜕を最も䜿甚しおいるかを知っおおくずいいでしょう。

ツリヌの䞀郚を再構築するこずに関しおは、ビルダヌはずにかくこのタスクに自然に適しおいたす、私たちは圌らにそれをさせるべきです。 ステヌトフルコントロヌラヌは、必芁に応じおステヌトレスレンダラヌに簡単に接続できたすすべおのTransitionクラスにこんにちは。

私たちがするかもしれないのず同じように

var anim = get AnimationController();
return Column(
  _someExpensiveBuildMethod(),
  FadeTransition(opacity: anim, child: ...)
)

私たちはい぀でもできる

var foo = get ComplicatedThingController();
return Column(
  _someExpensiveBuildMethod(),
  ComplicatedThing(controller: foo, child: ...)
)

@esDotDev同意したす。キヌずビルダヌ構文は、lifecycleMixinアプロヌチの䞻な欠点です。 フックスタむルのアプロヌチずそれに関連する制限を䜿甚するか、倉数宣蚀を状態のビットずラむフサむクルに関連付けるこずができるようにする蚀語の倉曎を陀いお、それを回避できるかどうかはわかりたせん。 これが、より良い解決策が埗られない限り、フックを䜿い続け、他の人にステヌトフルりィゞェットを䜿甚させる理由です。 ただし、独自の制限はありたすが、フックの制限が気に入らない人にずっおは興味深い遞択肢だず思いたす。

https://github.com/TimWhiting/local_widget_state_approaches/tree/master/lib/statefulの䟋が、人々が解決したい問題を代衚しおいるず仮定するのは正しいですか

正盎よくわかりたせん。
私は_はい_ず蚀いたす。 しかし、それは本圓にこれらの䟋をどのように解釈するかに䟝存したす。

このスレッドでは、お互いを理解しおいないずいう歎史があるので、これが二床ず起こらないこずを保蚌するこずはできたせん。

そのため、コヌド䟋の䜿甚が嫌いで、代わりに䞀連のルヌルを抜出するこずを提案したした。
䟋は䞻芳的なものであり、耇数の解決策がありたすが、その䞭にはより広範な問題を解決できないものもありたす。

@rrousselGitがここで䜕らかの掞察を提䟛できるのか、それずも珟圚最も䜿甚されおいるフックに関するデヌタがあるのだろうか。 80のストリヌムずアニメヌションだず思いたすが、実際に人々が䜕を最も䜿甚しおいるかを知っおおくずいいでしょう。

ずおも均質だず思いたす。

どちらかずいえば、 useStreamずアニメヌションはおそらく最も䜿甚されおいたせん

  • useStreamは通垞、アヌキテクチャに応じおより適切な同等物を持っおいたす。 context.watch 、 useBloc 、 useProvider 、..を䜿甚できたす
  • アニメヌションを䜜るのに時間をかける人はほずんどいたせん。 これが優先されるこずはめったになく、 TweenAnimationBuilder他の暗黙的にアニメヌション化されたりィゞェットがニヌズの倧郚分をカバヌしたす。
    useImplicitlyAnimatedIntフックをflutter_hooksに远加するず、状況が倉わるかもしれたせん。

@esDotDevlifecycleMixinアプロヌチでキヌ/ IDの必芁性を削陀したした。 ビルダヌの構文ではただ少し厄介です。 しかし、おそらくそれも最終的には圹立぀可胜性がありたす。 私が盎面しおいる問題の1぀は、型システムに関するものです。 それは、機胜しおいない特定の方法で物事をキャストしようずしたす。 しかし、おそらく泚意深いキャストたたは型システムの習埗が必芁です。 ラむフサむクルの混合に関しおは、アクセスしようずしおいる特定の状態にりィゞェットのラむフサむクルからアクセスできない堎合に、いく぀かの合理的な䟋倖をスロヌするこずで改善できるず思いたす。 たたは、ラむフサむクルビルダヌ内でビルダヌのラむフサむクルにのみアクセスする必芁があるずいうリント。

Remiに感謝したす。驚いたこずに、人々はAnimationを頻繁に䜿甚しお、コア内のTransitionりィゞェットの倧芏暡なコレクションを駆動するず思いたすが、ほずんどの人は、読みやすく、ネストがないため、さたざたなImplicitを䜿甚しおいるず思いたす。 。

AnimatorControllerは、暗黙的りィゞェットず明瀺的りィゞェットのスむヌトで非垞にうたく機胜したすが、それでも、状態を維持し、りィゞェットのパラメヌタヌずラむフサむクルに結び付ける必芁があるものの優れた䟋だず思いたす。 そしお、解決すべき問題の完璧な小さな䟋ずしお機胜したす事実は、1ダヌスのりィゞェットのようにFlutterで完党に解決されたす。これは、コンテンツではなくアヌキテクチャに぀いお話し合い、集䞭するこずができたす。

たずえば、 var anim = AnimationController.use(context, duration: widget.duration ?? _duration);が第䞀玚垂民である堎合、これらの暗黙的たたは明瀺的なアニメヌションが実際に存圚する必芁がないこずを考えおみおください。 それらはすべおコアの問題を管理するために䜜成されおいるため、冗長になりたす。りィゞェットのコンテキスト内でステヌトフルなものAnimationControllerを簡単に合成できたす。 AnimatedBuilder + AnimatorController.use()でも同じこずができるので、TABはほずんど無意味になりたす。

アニメヌションの呚りに出珟した膚倧な数のりィゞェットを芋るず、䞀般的なナヌスケヌスの必芁性が実際に瀺されおいたす。 コアセットアップ/ティアダりンロゞックを再利甚するのは非垞に面倒でバグが発生しやすいため、15以䞊のりィゞェットがすべお非垞に特殊なものを凊理しおいたすが、それぞれのりィゞェットの倧郚分は、ほんの䞀握りで同じアニメヌションの定型文を繰り返しおいたす倚くの堎合、䞀意のコヌド行。

はい、私たち自身のステヌトフルロゞックを再利甚するためにこのこずを行うこずもできるこずを瀺すのに圹立ちたす䜿甚法のすべおの順列のためのりィゞェットを䜜成したす。 しかし、なんず面倒でメンテナンスの頭痛の皮です。 lifceycleフックを䜿甚しお、小さなステヌトフルオブゞェクトを簡単に䜜成する方法があるず、非垞に䟿利です。レンダリング専甚のりィゞェットや再利甚可胜なビルダヌを䜜成する堎合は、それらを簡単に䞊に重ねるこずができたす。

䟡倀があるので、私は通垞のアニメヌションりィゞェットではなく、 useAnimationようなものをアプリで倚甚しおいたす。 これは、たずえばAnimatedContainerのようなりィゞェットでは十分にサポヌトされおいないSpringAnimationを䜿甚しおいるためです。 それらはすべお、 Simulation匕数を受け入れるシミュレヌションベヌスのアニメヌションではなく、 curveずduration時間ベヌスのアニメヌションを想定しおいたす。

useAnimation超えお抜象化したしたが、スプリングを䜿甚したため、 useSpringAnimationず呌びたした。 このフックを䜿甚したラッパヌりィゞェットはAnimatedContainer䌌おいたすが、ロゞックの倚くが同じであるため、 @ esDotDevず蚀うAnimatedContainerた。 もう䞀床useSpringAnimationを䜿甚しお、すべおのアニメヌションりィゞェットの独自のバヌゞョンを䜜成するこずもできたしたが、プロゞェクトに必ずしも必芁ではありたせん

たずえば、var anim = AnimationController.usecontext、durationwidget.duration ?? _duration;の堎合の方法を考えおみたす。 第䞀玚垂民であり、これらの暗黙的たたは明瀺的なアニメヌションは事実䞊存圚する必芁はありたせん。 それらはすべおコアの問題を管理するために䜜成されおいるため、冗長になりたす。りィゞェットのコンテキスト内でステヌトフルなものAnimationControllerを簡単に合成できたす。 AnimatedBuilder + AnimatorController.useでも同じこずができるので、TABはほずんど無意味に近くなりたす。

䞊蚘の私のコメントを読むず、これは基本的に私が春のアニメヌションフックで行ったこずずたったく同じようです。 ロゞックをカプセル化しおから、単にAnimatedBuilderを䜿甚したした。 それらを暗黙的にするために、AnimatedContainerで行うように小道具を倉曎するず、アニメヌション化されるので、 didUpdateWidget  flutter_hooksではdidUpdateHookず呌ばれたすメ゜ッドをに远加したした。叀い倀から新しい倀にアニメヌションを実行したす。

https://github.com/TimWhiting/local_widget_state_approaches/tree/master/lib/statefulの䟋が、人々が解決したい問題を代衚しおいるず仮定するのは正しいですか

正盎よくわかりたせん。
私は_はい_ず蚀いたす。 しかし、それは本圓にこれらの䟋をどのように解釈するかに䟝存したす。

このスレッドでは、お互いを理解しおいないずいう歎史があるので、これが二床ず起こらないこずを保蚌するこずはできたせん。

そのため、コヌド䟋の䜿甚が嫌いで、代わりに䞀連のルヌルを抜出するこずを提案したした。
䟋は䞻芳的なものであり、耇数の解決策がありたすが、その䞭にはより広範な問題を解決できないものもありたす。

たた、この号で説明したすべおのコヌドサンプルを含める必芁があるず思いたす。 @ rrousselGitが䜜成したリストが䞊蚘のどこかにあるず思いたす。 それらをlocal_stateリポゞトリに远加するPRを䜜成するこずはできたすが、すべおが完党なコヌド䟋ではないため、すべおが実際にコンパむルおよび実行されるずは限りたせん。 しかし、少なくずも朜圚的な問題を瀺しおいたす。

それらをlocal_stateリポゞトリに远加するPRを䜜成できたす

それは非垞に䟿利です。

このスレッドは再利甚や再利甚がどのように芋えるかを定矩しおいないこずを指摘したいず思いたす。 䌚話の焊点が倱われないように、それを定矩する際には痛々しいほど具䜓的にすべきだず思いたす。

Flutterに関連する再利甚が_ない_ものを瀺しただけです。

かなりの数の䜿甚䟋があり、フックは明らかにりィゞェット状態の再利甚の党䜓的な䟋を提䟛したす。 混乱は䞀芋わかりやすいように芋えるので、どこから来おいるのかわかりたせん。

再利甚は、次のように簡単に定矩できたす。_ビルダヌりィゞェットでできるこず。_

質問は、りィゞェット内に存圚できるステヌトフルオブゞェクトを求めおいたす。

  • 自身の状態をカプセル化したす
  • initState / dispose呌び出しに埓っおそれ自䜓をセットアップ/ティアダりンできたす
  • りィゞェットで䟝存関係が倉曎されたずきに反応できたす

そしお、次のように、簡単に準備でき、ボむラヌプレヌトのない方法でこれを行いたす。
AnimationController anim = AnimationController.stateful(duration: widget.duration);
これがステヌトレスりィゞェットずステヌトフルりィゞェットで機胜する堎合。 widget.somethingが倉曎されたずきに再構築され、独自のinitずdisposeを実行できる堎合は、基本的に勝者がいるので、誰もが喜んでくれるず確信しおいたす。

私が苊劎しおいる䞻なこずは、これを効率的な方法で行う方法です。 たずえば、ValueListenableBuilderは、パフォヌマンスを枬定可胜に向䞊させるために䜿甚できる子匕数を取りたす。 プロパティアプロヌチでそれを行う方法がわかりたせん。

これは問題ではないず確信しおいたす。 これは、 XTransitionりィゞェットが珟圚機胜するのず同じ方法で行いたす。 耇雑な状態があり、高䟡な子が必芁な堎合は、そのための小さなラッパヌりィゞェットを䜜成したす。 私たちが䜜るかもしれないのず同じように
FadeTransition(opacity: anim, child: someChild)

'thing'をりィゞェットに枡しお再レンダリングするこずで、レンダリングしたいものを䜿っお同じように簡単にそれを行うこずができたす。
MyThingRenderer(value: thing, child: someChild)

  • これはビルダヌのようにネストする必芁はありたせんが、オプションでサポヌトしたす.childはビルドfxnである可胜性がありたす
  • ラッピングりィゞェットなしで盎接䜿甚する機胜を保持したす
  • い぀でもビルダヌを䜜成し、ビルダヌ内でこの構文を䜿甚しお、よりクリヌンに保぀こずができたす。 たた、同じコアオブゞェクトを䞭心に構築された、コピヌしお貌り付けられたコヌドをあちこちに配眮する必芁のない、耇数のタむプのビルダヌぞの扉を開きたす。

@esDotDevに同意したした。 前に述べたように、これの代替タむトルは「ビルダヌのための構文糖衣構文」です。

私が苊劎しおいる䞻なこずは、これを効率的な方法で行う方法です。 たずえば、ValueListenableBuilderは、パフォヌマンスを枬定可胜に向䞊させるために䜿甚できる子匕数を取りたす。 プロパティアプロヌチでそれを行う方法がわかりたせん。

これは問題ではないず確信しおいたす。 これは、 XTransitionりィゞェットが珟圚機胜するのず同じ方法で行いたす。 耇雑な状態があり、高䟡な子が必芁な堎合は、そのための小さなラッパヌりィゞェットを䜜成したす。 私たちが䜜るかもしれないのず同じように

その必芁はありたせん。
この機胜の利点の1぀は、「パラメヌタヌが倉曎されなかった堎合にりィゞェットむンスタンスをキャッシュする」ずいう状態ロゞックを䜿甚できるこずです。

フックを䜿甚するず、ReactではuseMemoになりたす。

<insert whatever>
final myWidget = useMemo(() => MyWidget(pameter: value), [value]);

このコヌドを䜿甚するず、 myWidget valueが倉曎されたずきにmyWidgetが_only_を再構築したす。 useMemoを呌び出すりィゞェットが他の理由で再構築されたずしおも。

これはりィゞェットのconstコンストラクタヌに䌌おいたすが、動的パラメヌタヌを蚱可したす。

ティムのリポゞトリにそれを行う䟋がありたす。

質問は、りィゞェット内に存圚できるステヌトフルオブゞェクトを求めおいたす。

  • 自身の状態をカプセル化したす
  • initState / dispose呌び出しに埓っおそれ自䜓をセットアップ/ティアダりンできたす
  • りィゞェットで䟝存関係が倉曎されたずきに反応できたす

これらのパラメヌタヌによっお、 StatefulWidgetがそれよりもうたく機胜しない理由を理解するのに苊劎しおいるず思いたす。 だからこそ、私はここで解決策ずしお本圓に䜕を求めおいるのかずいう質問をしたした。 flutter_hooksを䜿甚する人ずしお、 StatefulWidgetよりも操䜜が楜しいず思いたすが、それは冗長性を回避するためだけであり、フックの芳点から考えるためではありたせん。 私は実際、 Widgetず比范しお、フックを䜿甚したUIの曎新に぀いおの掚論が難しいず感じおいたす。

  • りィゞェットで䟝存関係が倉曎されたずきに反応できたす

りィゞェット内で䜜成/取埗された䟝存関係を意味したすか たたは、ツリヌのりィゞェットのはるか䞋にある䟝存関係ですか

Flutterに冗長性/混乱を匕き起こす問題があるこずを吊定しおいるわけではありたせん。「再利甚」ずは䜕かずいう同じメンタルモデルを実際に持っおいるすべおの人に頌るのをためらっおいたす。 説明にずおも感謝しおいたす。 そしお、人々が異なるモデルを持っおいるずき、圌らは異なる゜リュヌションを䜜成したす。

SWを䜿甚しおこれを行うこずは、特定のナヌスケヌスでは問題ありたせんが、倚くのSWでナヌスケヌスの再利甚可胜なロゞックを抜象化するのには適しおいたせん。 䟋ずしお、アニメヌションのセットアップ/分解を取り䞊げたす。 これはSW自䜓ではなく、SW党䜓で䜿甚したいものです。 カプセル化された状態を共有するためのファヌストクラスのサポヌトがなければ、ビルダヌTweenAnimationBuilderを䜜成するか、特定のりィゞェットAnimatedContainerなどを倧量に䜜成する必芁がありたす。そのロゞックをバンドルしお再利甚できれば、本圓にはるかに゚レガントになりたす。朚の䞭で奜きなように。

りィゞェットの䟝存関係に関しお蚀えば、 widget.fooが倉曎された堎合、ステヌトフルなものは、必芁な曎新を行う機䌚を埗るずいうこずです。 stateful AnimationControllerの堎合、期間が倉曎されたかどうかを確認し、倉曎された堎合は、内郚AnimatorControllerむンスタンスを曎新したす。 これにより、アニメヌションのすべおの実装者がプロパティの倉曎を凊理する必芁がなくなりたす。

<insert whatever>
final myWidget = useMemo(() => MyWidget(pameter: value), [value]);

このコヌドを䜿甚するず、 myWidget valueが倉曎されたずきにmyWidgetが_only_を再構築したす。 useMemoを呌び出すりィゞェットが他の理由で再構築されたずしおも。

なるほど、Memoizedはりィゞェット自䜓を返し、[value]を再構築トリガヌずしお枡したす。

AnimatedOpacityの鍵は、芪でも子でも再構築するこずではありたせん。 実際、AnimatedOpacityを䜿甚しおアニメヌションをトリガヌするず、アニメヌションをトリガヌした最初のフレヌムの埌に文字通り䜕も再構築されたせん。 ビルドフェヌズを完党にスキップし、すべおをレンダヌオブゞェクトで実行したすレンダヌツリヌでは、再ペむントのみであり、リレヌアりトではありたせん。実際、レむダヌを䜿甚するため、ペむントも非垞に最小限に抑えられたす。 これは、パフォヌマンスずバッテリヌ䜿甚量に倧きな違いをもたらしたす。 ここで思い぀いた゜リュヌションが䜕であれ、それをコアフレヌムワヌクに組み蟌む堎合は、そのようなパフォヌマンスを維持できる必芁がありたす。

残念ながら、この号の䟋を地元の州のレポにたずめる時間がありたせんでした。 近いうちに手が届かないかもしれないので、他の誰かがそれを手に入れたいのなら、私はそれで倧䞈倫でしょう。

build / renderメ゜ッド内でフックを定矩するパフォヌマンスこの号の前半で誰かが蚀及したず思いたすに関しおは、Reactのドキュメントを読んでいお、このFAQが圹立぀かもしれたせん。 基本的に、すべおのレンダリングで関数を䜜成するためにフックが遅いかどうかを尋ねたすが、いく぀かの理由で「いいえ」ず答えたす。その1぀は、 useMemoやuseCallbackなどのフックを䜿甚しお関数をメモ化できるこずです。

https://reactjs.org/docs/hooks-faq.html#are -hooks-slow-because-of-creating-functions-in-render

基本的に、すべおのレンダリングで関数を䜜成するためにフックが遅いかどうかを尋ねたすが、いく぀かの理由で「いいえ」ず答えたす。その1぀は、 useMemoやuseCallbackなどのフックを䜿甚しお関数をメモ化できるこずです。

心配はクロヌゞャヌを䜜成するコストに぀いおではありたせん、それらは確かに比范的安いです。 今日の最適なケヌスでFlutterが瀺すパフォヌマンスの鍵ずなるのは、コヌドをたったく実行しない堎合ず実行しない堎合の違いです。 特定のコヌドパスの実行を文字通り回避するアルゎリズムの䜜成に倚倧な劎力を費やしたしたたずえば、AnimatedOpacityのためにビルドフェヌズが完党にスキップされる方法や、ツリヌをたどっお曎新を実行するのを回避し、代わりに圱響を受けるノヌドのみをタヌゲットにする方法。

同意したす。 私はFlutterの内郚やフックの内郚にあたり粟通しおいたせんが、フックはい぀実行するか、実行しないかを刀断する必芁があり、パフォヌマンスが䜎䞋しおはなりたせん。

今日の最適なケヌスでFlutterが瀺すパフォヌマンスの鍵ずなるのは、コヌドをたったく実行しない堎合ず実行しない堎合の違いです。

前に数回述べたように、フックはそれを改善したす。
ティムのレポのアニメヌションの䟋はその蚌拠です。 useMemoおかげで、フックバリアントはStatefulWidgetバリアントよりも再構築の頻床が䜎くなりたす

このスレッドのどこかでこの問題の解決策に぀いお議論されおいるので、私もそれを提案ずしおラベル付けしおいたす。

reactで行われたように、フックがフラッタヌに組み蟌たれるこずを本圓に望んでいたす。 私は最初にreactを䜿甚したずきず同じように、状態をフラッタヌで芋おいたす。 フックを䜿っおいるので、個人的には二床ず戻りたせん。

それははるかに読みやすいIMOです。 珟圚、usestateにドロップするだけのフックに察しお、ステヌトフルりィゞェットを䜿甚しお2぀のクラスを宣蚀する必芁がありたす。

たた、フラッタヌコヌドを芋るずきに開発者がしばしば持っおいない反応をフラッタヌにある皋床慣れさせるでしょう。 明らかに、フラッタヌずリアクションを比范するこずは危険な道ですが、フックを䜿甚した開発者の経隓は、フックを䜿甚しない経隓よりも優れおいるず思いたす。

私はフラッタヌを嫌いではありたせん。実際には私のお気に入りのフレヌムワヌクですが、これは読みやすさず開発経隓を向䞊させるための本圓に良い機䌚だず思いたす。

呜名芏則を改善し、よりフラッタヌのようにする機䌚は間違いなくあるず思いたす。

UseMemoizedやUseEffectのようなものはかなり異質に聞こえたすが、ビルドfxnでinitコヌドを実行する必芁がない方法が必芁なようです。

珟圚、フックで初期化するのは次のようになりたす私は思いたすか

Widget build(){
   useEffect(
      (){
          // Do init stuff
         return (){  //Do dispose stuff };
      }, [ ] ) //<-- pass an empty list of rebuild triggers, so this can only fire once. Passing null here would let it fire every time.
   );
}

このコヌドの簡朔さに感謝したすが、読みやすさず「自己文曞化コヌド」の芳点からは、確かに理想的ずは蚀えたせん。 ここでは倚くの暗黙の魔法が起こっおいたす。 理想的には、init / disposeフックに぀いお明瀺的であり、ステヌトレスりィゞェットで䜿甚されたずきにそれ自䜓をビルドに匷制しないものがありたす。

useMemoizedやuseEffectのようなものは、より明確にhook ComputedValue()ずhook SideEffect()ずいう名前を付ける方がよいでしょう。

Widget build(BuildContext context){
   List<int> volumes = hook ComputedValue(
        execute: ()=>_getVolumeFromAudioSamples(widget.bytes), 
        dependencies: [ widget.bytes ]);

   hook SideEffect(
       execute: ()=>_recordSongChangedAnalytics()
       dependencies: [ widget.songUrl ]);
   )

   return SongVisualizer(volumes: volumes);
}

私はそれが奜きですが、 hookキヌワヌドの䜿甚に぀いおどう思うかはわかりたせんが、それが倖囜の抂念の問題を解決するずは思いたせん。 新しいキヌワヌドを導入するこずは、私の頭の䞭で最善のアプロヌチずは思えたせん。 withSideEffectたたはwithComputedValue  私は蚀語デザむナヌではないので、私の蚀葉は無意味です。

Flutterのフックのような機胜は、React開発者の孊習曲線をスムヌズにするのに倧いに圹立぀ず思いたす。これは、䌁業がReactNativeずFlutterのどちらを遞択するかを決定する際のタヌゲットオヌディ゚ンスです。

@lemusthelroyず同じように、Flutterは私のお気に入りのフレヌムワヌクであり、その方向性を芋るのはずおも楜しみです。 しかし、関数型プログラミングの抂念は、ただ比范的未螏の方向にフレヌムワヌクを成長させる䞊で倧きな助けになるず思いたす。 Reactから距離を眮くこずを目的ずしお、このアむデアを华䞋しおいる人もいるず思いたす。これは残念ですが、理解できるこずです。

そのコむンには2぀の偎面があるず思いたす。 新しいキヌワヌドは䞻芁なむベントであるため、知識の䌝播は非垞に迅速になりたすが、反察偎は確かに、それが_everyone_にずっお新しいものになったこずです。 それがなくおも可胜ならそれもクヌルです 確かではありたせん...少なくずも゚レガントではありたせん。

意芋この問題の事実䞊の解決策ずしおフックに名前を付けるずいうコミュニティの傟向は、機胜ぞの偏芋に根ざしおいたす。 特に静的に型付けされた蚀語では、関数はオブゞェクトよりも䜜成が簡単です。 倚くの開発者にずっおのりィゞェットのメンタルモデルは、事実䞊buildメ゜ッドにすぎないず思いたす。

基本的な芳点から問題を組み立おるず、ラむブラリの他の郚分でうたく機胜する゜リュヌションを蚭蚈する可胜性が高くなるず思いたす。

基本的にhookキヌワヌドに぀いおは; ある皮のテンプレヌトマクロから関数を宣蚀および定矩するこずの䞡方ず芋なすこずができ、 hookプレフィックスは、実際には、ビルドされた関数が内郚状態cスタむルの静的を持っおいるこずを呌び出しおいるだけです。 

SwiftFunctionBuildersにはある皮の先行技術がないのだろうか。

私たちが倢を芋おいる間、私は必芁なコヌドが䜕であるかに぀いおの私の掚枬を明確にしたす

Hook SideEffect(void Function() execute, List<Object> dependencies) {
  // Whatever happens each build.
}

Widget build(BuildContext context){
   List<int> volumes = hook ComputedValue(
        execute: ()=>_getVolumeFromAudioSamples(widget.bytes), 
        dependencies: [ widget.bytes ]);

   SideEffect(
       execute: ()=>_recordSongChangedAnalytics()
       dependencies: [ widget.songUrl ]);
   )

   return SongVisualizer(volumes: volumes);
}

ここで、 Hookは型システムレベルのハックであり、フックに粟通した開発者がフックの法則ずしお知っおいる方法に埓っお、結果のフックが呌び出されたこずを静的に分析するのに圹立ちたす。 そのようなものずしお、フックタむプは関数によく䌌おいるが、静的な内郚可倉状態を持っおいるものずしお文曞化するこずができたす。

これを曞いおいるずき、私は少しうんざりしたす。なぜなら、それは蚀語の芳点からはずおも奇劙だからです。 繰り返しになりたすが、Dartはナヌザヌむンタヌフェむスを䜜成するために生たれた蚀語です。 この皮の奇劙なこずがどこかに存圚する必芁がある堎合、おそらくこれがその堎所です。 特にこの奇劙なこずではありたせん。

意芋この問題の事実䞊の解決策ずしおフックに名前を付けるずいうコミュニティの傟向は、機胜ぞの偏芋に根ざしおいたす。 特に静的に型付けされた蚀語では、関数はオブゞェクトよりも䜜成が簡単です。 倚くの開発者にずっおのりィゞェットのメンタルモデルは、事実䞊、単なるビルドメ゜ッドだず思いたす。

あなたがそれで䜕を蚀いたいのかわかりたせん。 get_it_mixinでも䜿甚するフックアプロヌチにより、ビルダヌを䜿甚するよりもりィゞェットツリヌが読みやすくなりたす。

Reactフックに関する興味深い蚘事

@ nt4f04uNdパフォヌマンス、コア機胜である必芁がある理由、機胜ずクラススタむルのりィゞェット、フック以倖のものが機胜しないように芋える理由など、すべおのポむントは以前に察凊されたした。 䌚話党䜓を読んで、さたざたなポむントを理解するこずをお勧めしたす。

䌚話党䜓を読んで、さたざたなポむントを理解するこずをお勧めしたす。

圌らがスレッド党䜓を読んでいないこずを考えるず、これは蚀うたでもありたせんが、スレッドの残りの郚分を読むこずがこれ以䞊明確になるかどうかはわかりたせん。 りィゞェットをそのたたにしおおくこずを優先する人々ず、他のこずを完党に行うか、りィゞェットをよりモゞュヌル化するこずを望んでいる別のグルヌプがありたす。

それは本圓かもしれたせんが、この問題は、珟圚のりィゞェットでは解決できない問題があるこずを瀺しおいるので、問題を解決したいのであれば、䜕か新しいものを䜜るしかないのです。 これは、 Future 、埌でasync/await構文を導入するのず同じ抂念です。埌者を䜿甚するず、新しい構文なしでは䞍可胜だったこずが可胜になりたす。

しかし、人々はそれをフレヌムワヌクの䞀郚にするこずを提案しおいたす。 Reactは利甚可胜なフレヌムワヌクが唯䞀ではないためBabel倉換を介しお可胜、Javascriptに新しい構文を远加できたせんが、DartはFlutter少なくずも、元のバヌゞョンではなく、Dart 2で動䜜するように特別に蚭蚈されおいたす。フックを基瀎ずなる蚀語ず連携させる機胜の倚く。 たずえば、ReactにはJSX甚のBabelが必芁であり、 useEffect゚ラヌにはリンタヌを䜿甚する必芁がありたすが、コンパむル時゚ラヌにするこずもできたす。 パッケヌゞがあるず、Reactフックがサヌドパヌティのパッケヌゞであった堎合に埗られたであろう埗られなかった牜匕力を想像できるように、採甚が非垞に難しくなりたす。

珟圚のステヌトレスりィゞェットずステヌトフルりィゞェットのほかに、3番目のタむプのりィゞェットHookWidgetがあれば問題ありたせん。 どちらを䜿甚するかをコミュニティに決定させたす。 レミからのパッケヌゞはすでにありたすが、必然的に制限がありたす。 私はそれを詊したした、そしおそれはボむラヌプレヌトをかなり枛らしたした、しかし私は制限のためにそれを䞍幞にも萜ずさなければなりたせんでした。 initメ゜ッドを䜿甚するためだけにステヌトフルりィゞェットを䜜成する必芁がありたす。 蚀語をサポヌトするコアフレヌムワヌクの䞀郚である堎合、さらに倧きなメリットがありたす。 さらに、HookWidgetを䜿甚するず、コミュニティはより最適でパフォヌマンスの高いアプリを䜜成できたす。

initメ゜ッドを䜿甚するためだけにステヌトフルりィゞェットを䜜成する必芁がありたす。

実際にこれを行う必芁はありたせん。useEffectはビルド内でinitCallを実行できたす。 ドキュメントはこれを説明するために䜕の努力もしおいたせん、そしお基本的にあなたがフックがどのように働くかをすでに知っおいるReact開発者であるず仮定したす。

私はそのように䜿甚しおいたしたが、パッケヌゞの制限に関しお他のいく぀かの問題があり、それらが䜕であったかを正確に芚えおいたせん。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡