Flutter BLoCパッケージ内のBLoCに関連するクラス.


Flutter BLoCパッケージ


BLoC Patternのパッケージの実装に役立ちます.
BLoC Patternを構成する際、BLoCイベントを定義し、状態の変化を観察するクラスを含むいくつかの利用可能な機能を事前に実装した.
関連ドキュメント

  • パッケージアドレス

  • 正式な書類


  • Cubit Class


    Cubitクラスはライブラリ内のBlocクラスの基礎である.
    Streamを使用してBlocクラスのクラスを簡単に作成します.
    emit関数を使用してステータスを変更できます.

    Cubit Classの使用例


    サンプルコード
    int形状状態を持つCounterCubitクラス
    class CounterCubit extends Cubit<int> {
      CounterCubit() : super(0);
    
      void increment() => emit(state + 1);
      void decrement() => emit(state - 1);
      void reset() => emit(0);
    }
    BlocObserverを使用して、すべてのCubitのステータスを表示できます.
    class CounterObserver extends BlocObserver {
      
      void onCreate(Cubit cubit) {
        super.onCreate(cubit);
        print('onCreate -- cubit: ${cubit.runtimeType}');
      }
    
      
      void onChange(Cubit cubit, Change change) {
        super.onChange(cubit, change);
        print('onChange -- cubit: ${cubit.runtimeType}, change: $change');
      }
    
      
      void onError(Cubit cubit, Object error, StackTrace stackTrace) {
        print('onError -- cubit: ${cubit.runtimeType}, error: $error');
        super.onError(cubit, error, stackTrace);
      }
    
      
      void onClose(Cubit cubit) {
        super.onClose(cubit);
        print('onClose -- cubit: ${cubit.runtimeType}');
      }
    }
    BlocObserverを使用するには、ドメインにクラスを指定する必要があります.
    void main() {
      Bloc.observer = CounterObserver();
    }
    あるいは、Cubitの状態だけを観察したい場合は、Cubitクラス内部で使用することができます.
    
      void onError(Object error, StackTrace stackTrace) {
        print("onError $error");
        super.onError(error, stackTrace);
      }
    
      
      void onChange(Change<int> change) {
        print("onChange $change");
        super.onChange(change);
      }
    Cubitを使用する必要があるコンポーネントにBlocProviderコンポーネントを使用してカプセル化します.
    例えば、MaterialAppはBlocProviderによって囲まれ、すべてのコンポーネントでCubitを使用する.
    class MyApp extends StatelessWidget {
      
      Widget build(BuildContext context) {
        return BlocProvider(
          create: (_) => CounterCubit(),
          child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
              visualDensity: VisualDensity.adaptivePlatformDensity,
            ),
            home: CounterPage(),
          ),
        );
      }
    }
    BlocBuilderを使用してCubitのステータスを取得し、テキストを描画します.
    class CounterView extends StatelessWidget {
      
      Widget build(BuildContext context) {
        final textTheme = Theme.of(context).textTheme;
    
        return Center(
          child: BlocBuilder<CounterCubit, int>(
            builder: (context, state) => Text(
              "$state",
              style: textTheme.headline2,
            ),
          ),
        );
      }
    }
    BlocProviderを使用してコンポーネントを囲むコンテキスト.read関数を使用してCubitインスタンスをインポートし、ステータスを使用して関数を変更します.
    BlocProviderサブコンポーネントのステータス変更とステータスサブスクリプションをテストするために、個別のコンポーネントを作成します.
    class CounterButtons extends StatelessWidget {
      
      Widget build(BuildContext context) {
        return Center(
          child: Column(
            children: [
              RaisedButton(
                  onPressed: () => context.read<CounterCubit>().increment(),
                  child: Icon(Icons.add)),
              RaisedButton(
                  onPressed: () => context.read<CounterCubit>().decrement(),
                  child: Icon(Icons.remove)),
              RaisedButton(
                  onPressed: () => context.read<CounterCubit>().reset(),
                  child: Icon(Icons.refresh)),
              RaisedButton(
                onPressed: () => Navigator.of(context).push(MaterialPageRoute(
                  builder: (context) => SecondPage(),
                )),
                child: Icon(Icons.send),
              )
            ],
          ),
        );
      }
    }
    class SecondPage extends StatelessWidget {
      
      Widget build(BuildContext context) {
        final textTheme = Theme.of(context).textTheme;
    
        return BlocBuilder<CounterBloc, int>(
          builder: (context, state) {
            return Scaffold(
              appBar: AppBar(title: Text("Second Page")),
              body: Center(
                child: Text(
                  "$state",
                  style: textTheme.headline2,
                ),
              ),
            );
          },
        );
      }
    }

    ボタンをクリックすると、ステータスが変化します.
    ステータスがBlocObserverクラスに変更されたことが検出されました.
    ステータスの前の値と現在の値は、いずれも確認可能な値です.
    flutter: onChange -- cubit: CounterCubit, change: Change { currentState: 0, nextState: 1 }
    flutter: onChange -- cubit: CounterCubit, change: Change { currentState: 1, nextState: 2 }
    Cubitを別のサブスクリプション・コンポーネントに移動すると、この値の出力が正しいことがわかります.

    Bloc Class




    BlocクラスはCubitクラスを継承し、基本的に同じ役割を果たす.
    ステータス変更を呼び出すために関数を定義するのではなく、イベントを直接定義できます.
    最大の違いは、イベントとして処理できることです.(Reduxの動作定義と同様)
    イベント処理プロセス

  • onEvent-イベント発生時に呼び出されます.

  • TransformEvents-受信イベントの変更

  • イベントをmapEventToState-TransnFormEventsに変換すると、変換されたイベントとともに呼び出され、受信したイベントに対してStateが生成されます.

  • TransformTransitions-終了ステータスの変更

  • onTransition-ステータスの更新前に呼び出し、現在のステータス、イベント、および次のステータスを表示します.

  • 通常、mapEventToStateを使用してイベントに応じてStateを変更し、返すだけです.
  • Bloc Classの使用例


    サンプルコード
    例では、イベントをenumとして定義します.
    CounterEventとint形式のState値を持つBlocクラス
    mapEventToState関数はジェネレータ関数であるため、Futureとは異なりasync*-yieldではなくasync-returnを使用します.
    returnとは異なり、ステータス値がyieldに返されるため、関数は終了しません.
    // 이벤트 정의
    enum CounterEvent { increment, decrement, reset }
    
    class CounterBloc extends Bloc<CounterEvent, int> {
      // 초기값 설정
      CounterBloc() : super(0);
    
      
      Stream<int> mapEventToState(CounterEvent event) async* {
        // 이벤트에 따라 상태 변화를 시켜준 뒤 리턴해준다
        switch (event) {
          case CounterEvent.increment:
            yield state + 1;
            break;
          case CounterEvent.decrement:
            yield state - 1;
            break;
          case CounterEvent.reset:
            yield 0;
            break;
        }
      }
    }
    BlocクラスはCubitクラスを継承するので,CubitクラスのようにBlocObserverを用いて状態を観察することができる.
    class CounterObserver extends BlocObserver {
      
      void onCreate(Cubit cubit) {
        super.onCreate(cubit);
        print('onCreate -- cubit: ${cubit.runtimeType}');
      }
    
      
      void onChange(Cubit cubit, Change change) {
        super.onChange(cubit, change);
        print('onChange -- cubit: ${cubit.runtimeType}, change: $change');
      }
    
      
      void onError(Cubit cubit, Object error, StackTrace stackTrace) {
        print('onError -- cubit: ${cubit.runtimeType}, error: $error');
        super.onError(cubit, error, stackTrace);
      }
    
      
      void onClose(Cubit cubit) {
        super.onClose(cubit);
        print('onClose -- cubit: ${cubit.runtimeType}');
      }
    }
    BlocObserverを使用するには、ドメインにクラスを指定する必要があります.
    void main() {
      Bloc.observer = CounterObserver();
    }
    あるいは、これらのBlocの状態変化のみを観察したい場合は、Blocクラス内でそれらを指定することもできます.
    
      void onEvent(CounterEvent event) {
        // TODO: implement onEvent
        super.onEvent(event);
      }
    
      
      void onTransition(Transition<CounterEvent, int> transition) {
        // TODO: implement onTransition
        super.onTransition(transition);
      }
    
      
      void onChange(Change<int> change) {
        // TODO: implement onChange
        super.onChange(change);
      }
    
      
      void onError(Object error, StackTrace stackTrace) {
        // TODO: implement onError
        super.onError(error, stackTrace);
      }
    Blocを使用する必要があるコンポーネントでは、BlocProviderコンポーネントを使用して囲みます.
    例では、MaterialAppをBlocProviderとしてカプセル化し、すべてのコンポーネントでCubitを使用します.
    class MyApp extends StatelessWidget {
      
      Widget build(BuildContext context) {
        return BlocProvider(
          create: (_) => CounterBloc(),
          child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
              visualDensity: VisualDensity.adaptivePlatformDensity,
            ),
            home: CounterPage(),
          ),
        );
      }
    }
    BlocBuilderを使用してBlocのステータスを取得し、テキストを描画します.
    class CounterView extends StatelessWidget {
      
      Widget build(BuildContext context) {
        final textTheme = Theme.of(context).textTheme;
    
        return Center(
          child: BlocBuilder<CounterBloc, int>(
            builder: (context, state) => Text(
              "$state",
              style: textTheme.headline2,
            ),
          ),
        );
      }
    }

  • BlocProviderを使用してコンポーネントを囲む場合の状態変換イベントの例

  • 対応するBlocを入力し、add関数として定義されたイベントを呼び出します.
  • class CounterButtons extends StatelessWidget {
      
      Widget build(BuildContext context) {
        return Center(
          child: Column(
            children: [
              RaisedButton(
                  onPressed: () =>
                      context.read<CounterBloc>().add(CounterEvent.increment),
                  child: Icon(Icons.add)),
              RaisedButton(
                  onPressed: () =>
                      context.read<CounterBloc>().add(CounterEvent.decrement),
                  child: Icon(Icons.remove)),
              RaisedButton(
                  onPressed: () =>
                      context.read<CounterBloc>().add(CounterEvent.reset),
                  child: Icon(Icons.refresh)),
              RaisedButton(
                onPressed: () => Navigator.of(context).push(MaterialPageRoute(
                  builder: (context) => SecondPage(),
                )),
                child: Icon(Icons.send),
              )
            ],
          ),
        );
      }
    }
    Cubitと同様に、ステータスの変化をログで確認できます.
    flutter: onChange -- cubit: CounterBloc, change: Change { currentState: 0, nextState: 1 }
    flutter: onChange -- cubit: CounterBloc, change: Change { currentState: 1, nextState: 2 }