Flutter 상태관리 (Flutter-bloc)

2022. 6. 22. 00:00Flutter

반응형

Flutter 에서 bloc 을 쉽게 사용할 수 있도록 해주는 plugin

일반 Bloc 과 함게 작동하도록 제작되었다.

 

Flutter 프로젝트를 처음에 생성하면 만들어 지는 Counter 예제를 수정해 보자

 

Cubit 을 이용한 counter 구현

counter_cubit.dart

import 'package:flutter_bloc/flutter_bloc.dart';

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);
  void decrement() => emit(state - 1);
}

counter_page.dart

import 'package:flutter/material.dart';
import 'package:flutter3/bloc/cubit/count_cubit.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (_) => CounterCubit(),
        child:const CounterPage(),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Counter Cubit')),
      body: BlocBuilder<CounterCubit, int>(
        builder: (context, count) => Center(
            child: Text('$count', style: Theme.of(context).textTheme.headline1)
        ),
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            child: const Icon(Icons.add),
            onPressed: () => context.read<CounterCubit>().increment(),
          ),
          const SizedBox(height: 4),
          FloatingActionButton(
            child: const Icon(Icons.remove),
            onPressed: () => context.read<CounterCubit>().decrement(),
          ),
        ],
      ),
    );
  }
}

BlocProvider 를 통해 cubit 와 page 를 연결해 준다.

 

body: 는 BlocBuilder<CubitClass명, state or stateValue> 를 감싼다.

 

onPressed 에서 context.read<CounterCubit>().increment() 를 통해 카운터 증가를 처리

onPressed 에서 context.read<CounterCubit>().decrement() 를 통해 카운터 감소를 처리

 

블록 옵저버 추가

class SimpleBlocObserver extends BlocObserver {
  @override
  void onChange(BlocBase bloc, Change change) {
   print('Cubit ${bloc.runtimeType} $change');
   super.onChange(bloc, change);
  }
}

main.dart 수정

void main() {
  BlocOverrides.runZoned(
      ()=>runApp(MainApp()),
    blocObserver: SimpleBlocObserver() // blocObserver 추가
  );
}

 

Bloc 를 이용한 counter 구현

counter_bloc.dart

import 'package:flutter_bloc/flutter_bloc.dart';
abstract class CounterEvent {}

class Increment extends CounterEvent {}
class Decrement extends CounterEvent {}

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<Increment>((event, emit) => emit(state + 1));
    on<Decrement>((event, emit) => emit(state - 1));
  }
}

counter_page.dart

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (_) => CounterBloc(),
        child: const CounterPage(),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Counter Bloc')),
      body: BlocBuilder<CounterBloc, int>(
          builder: (context, count) => Center(
              child: Text('$count', style: Theme.of(context).textTheme.headline1)
          ),
        ),
      floatingActionButton:  Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            child: const Icon(Icons.add),
            onPressed: () => context.read<CounterBloc>().add(Increment()),
          ),
          const SizedBox(height: 4),
          FloatingActionButton(
            child: const Icon(Icons.remove),
            onPressed: () => context.read<CounterBloc>().add(Decrement()),
          ),
        ],
      ),
    );
  }
}

BlocProvider 를 통해 bloc 과 page 를 연결해 준다.

 

body: 는 BlocBuilder<BlocClass명, state or stateValue> 를 감싼다.

onPressed 에서 context.read<CounterBloc>().add(Increment()) 를 통해 카운터 증가를 처리

onPressed 에서 context.read<CounterBloc>().add(Decrement()) 를 통해 카운터 감소를 처리

 

블록 옵저버 추가

class SimpleBlocObserver extends BlocObserver {
  @override
  void onChange(BlocBase bloc, Change change) {
    print('Bloc ${bloc.runtimeType} $change');
    super.onChange(bloc, change);
  }
}

 

관련영상

https://youtu.be/KQv4KDFJWZk

 

반응형

'Flutter' 카테고리의 다른 글