관리 메뉴

Bull

[Flutter::Bloc::utility] bloc_concurrency 약식 정리 본문

Software Framework/Flutter

[Flutter::Bloc::utility] bloc_concurrency 약식 정리

Bull_ 2024. 11. 26. 05:59

reference


pub.dev - bloc_concurrency
github - bloc concurrency

concept


  • bloc의 동시성 이벤트 처리를 관리해준다.
  • cubit은 이벤트를 정의하지 않고 메소드로 호출되기 때문에 cubit에서는 X

Usage


  • on 등록 메서드의 transformer 프로퍼티에 필요한 메소드를 담으면 된다.

type


  • concurrent() : 동시에 처리.
  • sequential() : 순차적으로 처리.
  • restartable() : 진행중인 이벤트를 멈추고 다시 시작.
  • droppable() : 이벤트를 진행하는 동안 들어오는 이벤트는 전부 무시.

code


concurrency.bloc.dart

import 'package:bloc/bloc.dart';
import 'package:bloc_concurrency/bloc_concurrency.dart';

sealed class CounterEvent {}
final class IncrementConcurrent extends CounterEvent {}
final class IncrementSequential extends CounterEvent {}
final class IncrementRestartable extends CounterEvent {}
final class IncrementDroppable extends CounterEvent {}

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<IncrementConcurrent>(
      _handleIncrementConcurrent,
      transformer: concurrent(),
    );

    on<IncrementSequential>(
      _handleIncrementSequential,
      transformer: sequential(),
    );  

    on<IncrementRestartable>(
      _handleIncrementRestartable,
      transformer: restartable(),
    );

    on<IncrementDroppable>(
      _handleIncrementDroppable,
      transformer: droppable(),
    );
  }

  /// Concurrent
  Future<void> _handleIncrementConcurrent(
    IncrementConcurrent event,
    Emitter<int> emit,
  ) async {
    await Future.delayed(Duration(seconds: 3));
    emit(state + 1);
  }

  /// Sequential
  Future<void> _handleIncrementSequential(
    IncrementSequential event,
    Emitter<int> emit,
  ) async {
    await Future.delayed(Duration(seconds: 3));
    emit(state + 1);
  }

  /// Restartable
  Future<void> _handleIncrementRestartable(
    IncrementRestartable event,
    Emitter<int> emit,
  ) async {
    await Future.delayed(Duration(seconds: 3));
    emit(state + 1);
  }

  /// Droppable
  Future<void> _handleIncrementDroppable(
    IncrementDroppable event,
    Emitter<int> emit,
  ) async {
    await Future.delayed(Duration(seconds: 3));
    emit(state + 1);
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'concurrency.bloc.dart';

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

final ThemeData darkTheme = ThemeData(
  brightness: Brightness.dark,
  colorScheme: ColorScheme.fromSeed(
    seedColor: Colors.lightBlue,
    brightness: Brightness.dark,
  ),
  useMaterial3: true,
);

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: darkTheme, // Apply the dark theme
      home: BlocProvider(
        create: (_) => CounterBloc(),
        child: CounterPage(),
      ),
    );
  }
}

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterBloc = context.read<CounterBloc>();

    return Scaffold(
      appBar: AppBar(title: const Text('Bloc Concurrency Example')),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Container(
            decoration: BoxDecoration(
              color: Colors.black54,
              borderRadius: BorderRadius.circular(12),
            ),
            padding: const EdgeInsets.all(16.0),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                BlocBuilder<CounterBloc, int>(
                  builder: (context, state) {
                    return Text(
                      'Current Count: $state',
                      style: const TextStyle(fontSize: 24, color: Colors.white),
                    );
                  },
                ),
                const SizedBox(height: 20),
                ElevatedButton(
                  onPressed: () => counterBloc.add(IncrementConcurrent()),
                  child: const Text('Increment Concurrent'),
                ),
                const SizedBox(height: 10),
                ElevatedButton(
                  onPressed: () => counterBloc.add(IncrementSequential()),
                  child: const Text('Increment Sequential'),
                ),
                const SizedBox(height: 10),
                ElevatedButton(
                  onPressed: () => counterBloc.add(IncrementRestartable()),
                  child: const Text('Increment Restartable'),
                ),
                const SizedBox(height: 10),
                ElevatedButton(
                  onPressed: () => counterBloc.add(IncrementDroppable()),
                  child: const Text('Increment Droppable'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

example을 통해 설명

  • concurrent() : 0.2초 간격으로 3번 누르면 0.2초 간격으로 3번 실행됨. (총 3.4초)
  • sequential() : 0.2초 간격으로 3번 누르면 3초마다 끝나고 실행됨. (총 9.2초)
  • restartable() : 0.2초 간격으로 3번 누르면 마지막으로 호출된 이벤트가 실행됨. (총 3.4초)
  • droppable() : 0.2초 간격으로 3번 누르면 최초 호출된 이벤트만 실행됨. (총 3초)

위젯은 썸네일 용