728x90
반응형
Bloc ① - 소개 https://dalgoodori.tistory.com/28
Bloc ② - Cubit 과 Bloc
Bloc ③ - Bloc Widgets https://dalgoodori.tistory.com/30
Bloc ④ - context.read, context.watch, context.select https://dalgoodori.tistory.com/31
Bloc ⑤ - Bloc Test https://dalgoodori.tistory.com/32
Cubit
- Cubit 은 Bloc 과 다르게 이벤트 기반이 아니라 정말 간단하게 상태를 관리할 수 있습니다.
- Provider 의 ChangeNotifier 와 비슷합니다.
생성
- Cubit 을 상속받는 클래스를 만들어주면 됩니다.
- 초기값은 내부적으로 넣을 수도 있고 initialState 로 외부적으로 초기값을 지정하는 방법도 있습니다.
- 상태는 emit 을 이용하여 변경합니다.
- 상태변경이 일어나면 onChange() 로 변경사항을 알 수 있습니다.
- 에러발생이 일어나면 onError() 로 알 수 있습니다.
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);
}
// 초기값은 외부에서
class CounterCubit extends Cubit<int> {
CounterCubit(int initialState) : super(initialState);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
// 변경 감지
@override
void onChange(Change<int> change) {
super.onChange(change);
print(change);
}
// 에러 감지
@override
void onError(Object error, StackTrace stackTrace) {
super.onError(error, stackTrace);
print('$error, $stackTrace');
}
}
사용
- Bloc 을 사용할 화면의 부모를 BlocProvider 로 지정하고 사용할 Cubit 을 지정합니다.
- Bloc 을 사용하는 화면에서 BlocBuilder 를 만들고 UI 를 그려줍니다.
- Cubit 사용은 context.read<CounterCubit>() 으로 합니다.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class BlocScreen extends StatelessWidget {
const BlocScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: BlocCounterScreen()
);
}
}
class BlocCounterScreen extends StatelessWidget {
const BlocCounterScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Bloc(Counter)'),
),
body: BlocBuilder<CounterCubit, int>(
builder: (context, count) => Center(child: Text('$count')),
),
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(),
),
],
),
);
}
}
Bloc
- 상태변경을 이벤트에 의존하는 클래스 입니다.
- Cubit 과 다르게 추적가능하다는 장점을 가지고 있습니다.
생성
- 위의 Cubit 예제인 카운팅 로직을 만들기 위해서 Bloc, Event, State 를 만들어야합니다.
- 카운팅 앱 같은 경우는 매우 간단하여 State 클래스를 만들지 않고 진행합니다.
1. Event
- abstract class 를 만듭니다.
- 로직마다 클래스를 만들어주고 만들었던 클래스를 상속시켜 줍니다.
abstract class CounterEvent {}
class CounterIncrementPressed extends CounterEvent {}
class CounterDecrementPressed extends CounterEvent {}
2. Bloc
- Bloc 클래스를 만들고 Bloc<{event}, {state}> 를 상속받습니다.
- 호출되는 이벤트를 통해 state 가 증감 됩니다.
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<CounterIncrementPressed>((event, emit) {
emit(state +1);
});
on<CounterDecrementPressed>((event, emit) {
emit(state -1);
});
}
}
사용
- Bloc 을 사용할 화면의 부모를 BlocProvider 로 지정하고 사용할 Bloc 을 지정합니다.
- Bloc 을 사용하는 화면에서 BlocBuilder 를 만들고 UI 를 그려줍니다.
- Bloc 사용은 context.read<CounterBloc>() 으로 하고 해당 이벤트들을 호출합니다.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class BlocScreen extends StatelessWidget {
const BlocScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterBloc(), // Bloc 넣기
child: BlocCounterScreen()
);
}
}
class BlocCounterScreen extends StatelessWidget {
const BlocCounterScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Bloc(Counter)'),
),
body: BlocBuilder<CounterBloc, int>(
builder: (context, count) => Center(child: Text('$count')),
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () => context.read<CounterBloc>().add(CounterIncrementPressed()),
),
const SizedBox(height: 4),
FloatingActionButton(
child: const Icon(Icons.remove),
onPressed: () => context.read<CounterBloc>().add(CounterDecrementPressed()),
),
],
),
);
}
}
728x90
반응형
'Flutter > Package' 카테고리의 다른 글
[Flutter] Bloc ④ - context.read, context.watch, context.select (0) | 2022.08.05 |
---|---|
[Flutter] Bloc ③ - Bloc Widgets (0) | 2022.08.04 |
[Flutter] Bloc ① - 소개 (0) | 2022.08.03 |
[Flutter] Provider (0) | 2022.07.27 |
[Flutter] Hive (0) | 2022.07.26 |