1. ホーム
  2. flutter

StatefulWidgetの外から状態を制御する

2024-01-01 10:40:31

質問

StatefulWidgetの状態をWidgetの状態の外側で制御するためのベストプラクティスを理解しようとしています。

私は以下のインターフェイスを定義しています。

abstract class StartupView {
  Stream<String> get onAppSelected;

  set showActivity(bool activity);
  set message(String message);
}

StatefulWidgetを作成したい。 StartupPage を作りたいと思います。このWidgetは次のようなことを期待します。

  1. ボタンが押されると、onAppSelectedストリームでイベントが送信されます。コントローラはこのイベントを聞き、何らかのアクション(データベース呼び出し、サービス要求など)を実行します。

  2. コントローラは showActivity または set message を使用すると、ビューにメッセージとともに進行状況を表示させることができます。

Stateful WidgetはプロパティとしてStateを公開しないので、Stateの属性にアクセスして変更するための最良の方法がわかりません。

私が期待する使い方は、次のようなものです。

Widget createStartupPage() {
    var page = new StartupPage();
    page.onAppSelected.listen((app) {
      page.showActivity = true;
      //Do some work
      page.showActivity = false;
    });
  }

で返したい状態を渡してWidgetをインスタンス化することを考えてみました。 createState() に渡すことでインスタンス化することも考えましたが、それは間違っているように感じます。

なぜ私たちがこのようなアプローチをとっているのか、いくつかの背景を説明します。現在、私たちはDartのWebアプリケーションを持っています。ビューとコントローラーの分離、テスト容易性、そしてFlutterへの前向きな考えのために、私たちはアプリケーション内のすべてのビューに対してインターフェースを作成することに決めました。これにより、WebComponentやFlutter Widgetがこのインターフェイスを実装し、すべてのコントローラロジックを同じにすることができるようになります。

どのように解決するのか?

静的メソッドで状態のウィジェットを公開することができます。flutterのサンプルのいくつかはこの方法をとっており、私もそれを使うようになりました。

class StartupPage extends StatefulWidget {
  static _StartupPageState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<_StartupPageState>());

  @override
  _StartupPageState createState() => new _StartupPageState();
}

class _StartupPageState extends State<StartupPage> {
  ...
}

次に、この状態にアクセスするには StartupPage.of(context).doSomething(); .

ここでの注意点は、そのページを持つBuildContextをそのツリーのどこかに持っている必要があることです。