Flutter

10-1. freezed의 다른 기능들

모리선생 2023. 4. 9. 19:29
728x90

목표

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을 사용하여 실제로 어떻게 사용이 가능한지 다음 장에서 다뤄보도록 합시다.

728x90

'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