Bloc의 사용법<2>

enoch·2022년 4월 21일
1

플러터

목록 보기
17/17
post-thumbnail

이제 사용을 해보자

  1. xx_state.dart

먼저 보다 편리하게 사용하기위해서 freezed라는 라이브러리를 사용한다.
겁나편한데다가 코드도 말끔해지니 사용을 추천한다

/// freezed사용전 Equatable 을 사용해서 해당 클래스에서의 equals를 구현
/// copywith역시 따로 지정해주어야한다
part of 'splash_bloc.dart';

class SplashState extends Equatable {
  final bool isLoading;
  
  List<Object?> get props => [isLoading];

  const SplashState({this.isLoading = true});

  SplashState copyWith({
    bool? isLoading,
  }) {
    return SplashState(
      isLoading: isLoading ?? this.isLoading,
    );
  }
}

위에 내용은 기본적으로 스테이트를 지정하기위해 가장 기본적인부분이다.
copywith가없으면 새로운 스테이트를 emit하기 힘들고 equals가없다면 state의 변화를 감지하지못해 뷰가 업데이트되지않는다.

하지만 위의 방법으로 만든다면 변수를 하나추가할대마다 props에 집어넣고 copywith를 다시 만들어야하고 생성자 내부 그리고 바깥에도 새로운 변수를 추가해야한다.

/// freezed사용전 Equatable 을 사용해서 해당 클래스에서의 equals를 구현
/// copywith역시 따로 지정해주어야한다
part of 'splash_bloc.dart';

class SplashState extends Equatable {
  final bool isLoading;
  final bool newVar
  
  List<Object?> get props => [isLoadin,newVar];

  const SplashState({this.isLoading = true,required this.newVal});

  SplashState copyWith({
    bool? isLoading,
    bool? newVar
  }) {
    return SplashState(
      isLoading: isLoading ?? this.isLoading,
      newVar:newVar??this.newVar
    );
  }
}

이렇게 변수하나만 넣었는데도 5줄을 수정해야하는 번거로움있다.

그럼 freezed를 쓴다면?

part of 'splash_bloc.dart';


class SplashState with _$SplashState {
  const factory SplashState({
    (true) bool isLoading,
  }) = _SplashState;
}

이게 끝이다. 해당 코드는 맨위에 써져있는 코드와 같은 기능을 하는것은 물론 null의 copy toString 등등 더많은 기능들이 포함되어있다.

이건 이포스트의 중점이 아니니 검색해보길 바란다.

이렇게 스테이트를 지정했다면 다음은 event이다

  1. xxx_event.dart
part of 'splash_bloc.dart';

abstract class SplashEvent extends Equatable {
  const SplashEvent();

  
  List<Object?> get props => [];
}

class SplashInitEvent extends SplashEvent {}

이건 equals기능만 사용하면되기때문에 freezed를 사용하지않았다.
freezed는 그래도 코드제너레이터기때문에 이렇게 ==연산만 필요할때는 equatable을 사용하는게 좋은것같았다.

이벤트를 하나를 지정하고 나머지 이벤트들은 기본이벤트를 extends시켜서 사용한다.

해당 이벤트가 실행되었을때 필요한 변수가있다면 해당 이벤트에 멤버변수를 선언해서 사용하면된다.

  1. xxx_bloc.dart
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'splash_bloc.freezed.dart';
part "splash_event.dart";
part "splash_state.dart";

class SplashBloc extends Bloc<SplashEvent, SplashState> {
  SplashBloc(SplashState initialState) : super(initialState) {
    on<SplashInitEvent>(_splashInitEvent);
  }
  Future<void> _splashInitEvent(SplashEvent event, Emitter emit) async {
    for (int i = 0; i < 101; i++) {
      emit(state.copyWith(rate: i));
      await Future.delayed(const Duration(milliseconds: 100));
    }
    emit(state.copyWith(isLoading: false));
  }

해당 파일이 위 두개의 파일의 주체가 되기때문에 import 와 part를 시켜야되는 부분이 많다.

on<Event>(_onEvent);

를 사용해서 해당 이벤트를 등록한뒤에 이벤트가 실행되었을경우의 로직을 메서드로 선언하면 끝이다.

위에 내용은 SplashInitEvent가 splashbloc에서 실행되었다면 _splashInitEvent가 실행되어서 해당 state 내부에 rate를 100으로 올려준다음 마지막에 로딩이 끝났다고 알려주는 로직이다

 BlocBuilder<SplashBloc, SplashState>(builder: (context, state) {
              return Text(
                state.isLoading ? "${state.rate}%" : "로딩 완료",
                style: _text.bodyText1,
              );
            }),

이제 위에내용을 뷰에서 확인할수있다.

결과

profile
플러터존잼

0개의 댓글