목표
freezed 플러그인을 알아보고 bloc과 함께 사용하는 법을 연습해본다. 실사용 예제를 통해, 해당 방법을 익힌다.
*해당 내용은 본인의 개발 공부에 있어서 여러가지 참고하며 기록했던 내용을 복기하고 이해하고자 작성한 블로그 글입니다. 같이 공부를 해나가며 Flutter라는 언어에 취미를 가지신 분 들이 개념을 잡는데 도움이 되었으면 합니다. 참고한 홈페이지 등에 대해서는 각 페이지별 하단에 명시하여 두었습니다. 수정 및 문의 사항이 있으면 알려주시길 바랍니다.
4. 연산 비교와 hashcode
방금 말씀드렸던 toJson, toString외에도 == 함수 및 hashCode 함수도 자동으로 override를 합니다. 클래스의 인스턴스를 비교할때 단순비교시에는 값이 차이가 난다고 나타날겁니다, 만약 override가 되어있지 않다면요. 하지만 freezed에서는 자동으로 ==와 hashcode 함수를 override하여 비교가 가능합니다.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('freezed')),
body: Column(
children: [
// Text(person1.id),
// Text(person1.name),
// Text(person1.age.toString()),
// Text(person1.toString()),
SizedBox(
height: 30,
),
Text((person1 == person2).toString()),
],
),
);
}
5. Assert
함수의 immutability를 검증하는데 사용되는 것으로 boolean 표현식을 인자로 받습니다.
- true: 동작 하지 않음
- false: 예외 발생 후 프로그램 중단
@Assert annotation을 이용한다면 특정 property의 값을 제한 할 수 있습니다.
예시를 보자면 다음과 같겠네요.
@ person.dart
// This file is "main.dart"
import 'package:freezed_annotation/freezed_annotation.dart';
// required: associates our `main.dart` with the code generated by Freezed
part 'person.freezed.dart';
// optional: Since our Person class is serializable, we must add this line.
// But if Person was not serializable, we could skip it.
part 'person.g.dart';
@freezed
class Person with _$Person {
///Assert를 사용하여 변수 값을 제한
@Assert('name.length < 5', 'The maximum name you can type is 5.')
const factory Person({
required String id,
required String name,
required int age,
}) = _Person;
factory Person.fromJson(Map<String, Object?> json) => _$PersonFromJson(json);
}
6. Method 및 getter 작성
@freezed 어노테이션을 사용한다면 불변의 데이터 클래스를 생성할 수 있습니다. 하지만 이러한 클래스는 생성자 매개변수와 함께 자동으로 일반적인 메소드와 getter가 생성이됩니다. 기본적인 메소드나 getter외에도 필요한 메소드나 getter를 정의할 수 있습니다.
@ person.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'person.freezed.dart';
part 'person.g.dart';
@freezed
class Person with _$Person {
const factory Person({
required String id,
required String name,
required int age,
}) = _Person;
factory Person.fromJson(Map<String, Object?> json) => _$PersonFromJson(json);
/// 메소드나 getter 작성시 추가 필요
Person._();
/// custom method: otherAge 매개변수와 현재 객체의 age 필드를 비교하여 true 또는 false를 반환
bool isOlderThan(int otherAge) {
return age > otherAge;
}
}
7. copy
Immutable 데이터 클래스는 copyWith 메소드를 사용하여 새로운 객체를 생성할 수 있습니다. copyWith 메소드는 현재 객체의 모든 필드를 복사하고, 필요한 필드만 변경하여 새로운 객체를 생성하도록 합니다. 즉, 기존 객체 변경도 필요 없을 뿐더러, 번거로운 작업도 피할 수 있습니다.
이를 사용하기 위해서는 기존의 main.dart를 살짝 수정할 필요가 있습니다. 왜냐면 person1 변수를 초기화 하는 과정에서 State 클래스의 인스턴스인 _HomeState가 아직 완전히 생성되지 않은 상태이기 때문입니다. 그래서 지금부터 할것은 person1을 초기화 하는 작업을 initState() 메서드에서 수행하도록 만들 겁니다.
person1과 person2 변수는 late 키워드로 나중에 초기화 하도록 설정하고 _HomeState클래스에서 initState() 메서드를 오버라이드 합니다. person1과 person2를 초기화 하는 작업을 이렇게 수행하여, copyWith가 정상적으로 작동하도록 만듭니다.
class _HomeState extends State<Home> {
late final Person person1;
late final Person person2;
@override
void initState() {
super.initState();
person1 = Person(id: 'hi', name: 'SSH', age: 20);
person2 = person1.copyWith(id: 'hey');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('freezed')),
body: Column(
children: [
Text(person2.toString()),
],
),
);
}
}
지금까지가 거의 중요한 것들은 다 커버를 한 것같습니다.
그럼 freezed와 궁합이 잘맞다는 bloc을 사용하여 실제로 어떻게 사용이 가능한지 다음 장에서 다뤄보도록 합시다.
'Flutter' 카테고리의 다른 글
11-1. BLoC의 구조 (상세) (0) | 2023.04.10 |
---|---|
11. BLoC (0) | 2023.04.09 |
10. freezed (0) | 2023.04.09 |
7-2. Throttle 실습 (0) | 2023.04.03 |
7-1. Debounce 실습 (0) | 2023.04.03 |