Bloc 간단 정리

순순·2024년 11월 22일

Flutter

목록 보기
9/16

블록 공식 사이트 참고

Bloc 의 장점

  • 뷰 영역과 비즈니스 영역을 쉽게 구분할 수 있다.
  • 테스트 하기 쉽고, 재사용 가능
    • bloc test 제공
  • 이벤트 트레킹 통합 관리 가능
    • 블럭 observer

Bloc 위젯 종류

  • BlocBuilder
  • BlocSelector
  • BlocProvider
  • MultiBlocProvider
  • BlocListener
  • MultiBlocListener
  • BlocConsumer
  • RepositoryProvider
  • MultiRepositoryProvider

BlocProvider


  • bloc 이나 cubit 을 사용하기 위해서는 context 에 등록해줘야 함. 이 등록 작업을 도와주는 위젯이 blocProvider.
  • create 부분에 해당 블럭을 리턴하면 된다.
  • child = 블럭의 영향을 받을 영역 = 자식 위젯
  • lazy = 샘플 블럭을 어느 시점에서 생성할건지 지정 (지연초기화 옵션)
return BlocProvider(
	create: (context) => SampleBloc(),
	lazy: false,
	child: SamplePage(),
);
  • Bloc Provider 생성 예제 코드
    import 'package:flutter/material.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:flutter_bloc_widget_sample/src/bloc/sample_bloc.dart';
    
    // ProviderPage
    class BlocProviderPage extends StatelessWidget {
      const BlocProviderPage({super.key});
    
      
      Widget build(BuildContext context) {
      // 프로바이더 선언
        return BlocProvider(
          create: (context) => SampleBloc(),
          lazy: false,
          child: SamplePage(),
        );
      }
    }
    
    // SamplePage
    // 나타낼 view
    class SamplePage extends StatelessWidget {
      
      Widget build(BuildContext context) {
        return Scaffold(
          body: const Center(
            child: Text('Bloc Provider Sample'),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              context.read<SampleBloc>().add(SampleEvent());
            },
          ),
        );
      }
    }
    
    ---
    
    // SampleBloc
    import 'package:bloc/bloc.dart';
    
    // Bloc 선언
    class SampleBloc extends Bloc<SampleEvent, int> {
      SampleBloc() : super(0) {
        print('init Samplebloc');
        on<SampleEvent>((event, emit) {
          print('Sample Event Called');
        });
        on<AddSampleEvent>((event, emit) {
          emit(state + 1);
        });
      }
    }
    
    // bloc event
    class SampleEvent {}
    
    class AddSampleEvent extends SampleEvent {}
    

MultiBlocProvider


  • BlocProvider 다중 등록

일반 프로바이더로 여러 개 등록하는 예시

return BlocProvider<BlocA>(
	create: (BuildContext context) => BlocA(),
	child: BlocProvider<BlocB>(
		create: (BuildContext context) => BlocB(),
		child: BlocProvider<BlocC>(
			create: (BuildContext context) => BlocC(),
			child: const ChildA(),
		),
	),
);

멀티 프로바이더 사용하여 등록하는 예시

return MultiProvider(
	providers: [
		BlocProvider(create: (context) => BlocA()),
		BlocProvider(create: (context) => BlocB()),
		BlocProvider(create: (context) => BlocC()),
	],
	child: const ChildA(),
);

BlocBuilder


  • BlocProvider 로 생성된 bloc 을 사용할 때 쓰는 위젯
  • bloc 을 지정하는 케이스의 경우, 특별한 케이스에서 사용하라고 권장한다.. buildContext 를 사용해서 접근할 수 없는 경우 (ex. showDialog 같은 경우)
  • buildWhen 옵션을 통해 필요한 조건일 때만 변화를 줄 수 있다.
    • buildWhen 내에 선언한 조건이 참일 때 builder 에 있는 내용으로 빌드 시킴.

샘플 블럭은 상태관리를 int 타입으로만 하고 있다…

child: BlocBuilder<SampleBloc, int>(
	builder: (context, state) {
	return Text{
		state.toString(),
		style: const TextStyle(fontSize: 70),
		}
	}
);

builder 예제 코드 + 블럭 dialog 등록

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_bloc_widget_sample/src/bloc/sample_bloc.dart';

class BlocBuilderPage extends StatefulWidget {
  const BlocBuilderPage({super.key});

  
  State<BlocBuilderPage> createState() => _BlocBuilderPageState();
}

class _BlocBuilderPageState extends State<BlocBuilderPage> {
  
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => SampleBloc(),
      lazy: false,
      child: SamplePage(),
    );
  }
}

class SamplePage extends StatelessWidget {
  //bloc을 등록해야 사용이 가능한 케이스
  late SampleBloc sampleBloc;
  void _showMessage(BuildContext context) {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext _) {
        return AlertDialog(
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
          title: const Text('Title'),
          content: BlocBuilder<SampleBloc, int>(
            bloc: sampleBloc,
            builder: (context, state) {
              return Text(state.toString());
            },
          ),
          actions: [
            ElevatedButton(
              child: const Text("확인"),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        );
      },
    );
  }

  
  Widget build(BuildContext context) {
    sampleBloc = context.read<SampleBloc>();
    return Scaffold(
      body: Center(
        child: BlocBuilder<SampleBloc, int>(
          buildWhen: (previous, current) {
            return current > 10;
          },
          builder: (context, state) {
            return Text(
              'index : $state',
              style: const TextStyle(fontSize: 70),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // context.read<SampleBloc>().add(AddSampleEvent());
          _showMessage(context);
        },
      ),
    );
  }
}
profile
플러터와 안드로이드를 공부합니다

0개의 댓글