web-dev-qa-db-ja.com

ブロック、フラッター、ナビゲーション

ほとんどのように、私はBloc and flutterとDartが初めてで、頭を包んでいます。私はググって、ここの投稿を調べましたが、本当に答えは見つかりませんでした。

これは、ブロックとフラッターによるナビゲーションについてです。ログインの例を見てみましょう。そのため、その後ろにブロックがあるログインページがあり、ある時点で誰かがボタンを押してログインします。

したがって、検証を行うブロック内の関数を呼び出すことができます。これは厳格なアプローチに反することだと思いますが、これをしている人はいます。しかし、ログインが成功した場合、どのように次の画面に移動しますか?あなたはブロックでナビゲートすることになっていますか?

しかし、そのログインページがStreamBuilderを使用して状態を変更している場合、ビルダーにナビゲートを追加することもできませんか?ナビゲーションを返すことはできません。ウィジェットを返します。

Initstateはナビゲートできる場所ですが、ブロックの状態変化をリッスンするinitstateにストリームビルダーを作成できますか?

現時点では少し混乱していますが、これは想定であるため、頑張っています...

ポールに感謝

25
paulinventome

BLoCがtheであるという神話をすぐに理解するには:状態を処理するための完璧な方法はありません。すべての状態管理アーキテクチャは、いくつかの問題を他の問題よりも解決します。常にトレードオフがあり、アーキテクチャを決定する際にはそれらを認識することが重要です。

一般的に、優れたアーキテクチャは実用的です:最小限のオーバーヘッドしか必要とせず、スケーラブルで拡張可能です。実用性に関する人々の見解は異なるため、アーキテクチャには常に意見が含まれるため、アプリにBLoCを採用する方法について個人的な見解を説明するため、以下を詳細に検討してください。

BLoCは、1つの特徴的な要素であるストリームのため、Flutterの状態管理に非常に有望なアプローチです。 UIをビジネスロジックから切り離すことができ、古くなったウィジェットサブツリー全体を再構築するFlutter風のアプローチでうまく機能します。当然、BLoCとの間のすべての通信はストリームを使用する必要がありますよね?

_+----+  Stream   +------+
| UI | --------> | BLoC |
|    | <-------- |      |
+----+   Stream  +------+
_

まあ、ちょっと。

覚えておくべき重要なことは、状態管理アーキテクチャは目的を達成するための手段であるということです;あなたはそれのために何かをすべきではありませんが、オープンマインドを保ち、各オプションの長所と短所を注意深く評価してください。 BLoCをUIから分離する理由は、BLoCがUIの構造を気にする必要がないためです。これは、いくつかのニースシンプルストリームを提供するだけで、データで発生することはすべてUIの責任です。

しかし、ストリームはBLoCからUIに情報を転送する素晴らしい方法であることが証明されていますが、逆方向に不必要なオーバーヘッドが追加されます。ストリームは、データの連続ストリーム(名前でも)を転送するように設計されていますが、時々、UIはBLoCで単一のイベントをトリガーする必要があるだけです。だからこそ、_Stream<void>_ sまたは同様のハッキングソリューション¹が、厳密にBLoC-yの方法に準拠するために表示されることがあります。

また、BLoCからのストリームに基づいて新しいルートをプッシュする場合、BLoCは基本的にUIフローを制御しますが、UIとビジネスロジックの両方を直接制御するコードを持つことは、防止しようとしたまさにその通りです!

そのため、一部の開発者(私を含む)は、完全にストリームベースのソリューションを使用せず、UIからBLoCでイベントをトリガーするカスタムの方法を採用しています。個人的には、メソッド呼び出し(通常はFuturesを返す)を使用してBLoCのイベントをトリガーします。

_+----+   method calls    +------+
| UI | ----------------> | BLoC |
|    | <---------------- |      |
+----+   Stream, Future  +------+
_

ここで、BLoCは「ライブ」であるデータに対してStreamsを返し、Futuresをメソッド呼び出しへの応答として返します。

あなたの例でそれがうまくいく方法を見てみましょう:

  • BLoCは、ユーザーがログインしているかどうかの_Stream<bool>_、または_Stream<Account>_を提供できます。ここで、Accountにはユーザーのアカウント情報が含まれています。
  • BLoCは、ログインが成功した場合は何も返さない、そうでない場合はエラーをスローする非同期Future<void> signIn(String username, String password)メソッドを提供することもできます。
  • UIはそれ自体で入力管理を処理し、ログインボタンが押されると、次のようなものをトリガーできます。
_try {
  setState(() => _isLoading = true); // This could display a loading spinner of sorts.
  await Bloc.of(context).signIn(_usernameController.text, _passwordController.text);
  Navigator.of(context).pushReplacement(...); // Push logged in screen.
} catch (e) {
  setState(() => _isLoading = false);
  // TODO: Display the error on the screen.
}
_

このようにして、懸念事項を適切に分離します。

  • BLoCは実際に、本来あるべきこと、つまりビジネスロジック(この場合は、ユーザーのサインイン)を処理します。
  • UIは次の2つの点のみを考慮します。
    • Streamsおよび
    • bLoCでユーザーアクションをトリガーし、その結果に基づいてUIアクションを実行することにより、ユーザーアクションに反応します。²

最後に、これは、複雑なアプリで状態を処理するさまざまな方法を試すことにより、時間とともに進化した唯一の可能なソリューションであることを指摘しておきます。状態管理がどのように機能するかについて、さまざまな視点を理解することが重要です。そのため、おそらく "Fragmatic State Management in Flutter" セッションをGoogle I /で見て、そのトピックをさらに掘り下げることをお勧めしますO.

[〜#〜] edit [〜#〜]:このアーキテクチャが Brian Eganのアーキテクチャサンプル で見つかりました。 「シンプルBLoC」。さまざまなアーキテクチャについて知りたい場合は、リポジトリを確認することをお勧めします。


B BLoCアクションに複数の引数を提供しようとすると、さらに醜くなります。これは、ストリームに渡すためだけにラッパークラスを定義する必要があるためです。

²Idoアプリの起動時に少し見苦しくなります:BLoCのストリームをチェックしてユーザーを適切な画面にリダイレクトするだけのスプラッシュ画面が必要ですサインインしたかどうかに基づいて。このルールの例外は、ユーザーがアクション(アプリの起動)を実行したために発生しますが、Flutterフレームワークでは直接フックすることはできません(少なくとも私の知る限り、エレガントではありません)。

21
Marcel

BlocListenerはおそらく必要なウィジェットです。状態が(たとえば)LoginSuccessに変化した場合、ブロックリスナーは通常のNavigate.of(context)を呼び出すことができます。 ここの例はBlocListenerの動作を示しています ですが、ナビゲートする代わりにスナックバーを表示します。

別のオプションは、イベントにコールバックを渡すことです。

 BlocProvider.of<MyBloc>(context).add(MyEvent(
              data: data,
              onSuccess: () {
                Navigator.Push(
                  context,
                  MaterialPageRoute(builder: (context) {
                    return HomePage();
                  }),
                );
              }));
2
34m0