flutter freezed (1)

Sunny·2022년 6월 6일

freezed

code generator 기능을 함 (data-classes / unions / pattern-matching / cloning

역할

생성자 + 속성 / Equatable / copyWith / (de/serialization handling) 기능을 해줌


설치방법

$ flutter pub add freezed_annotation
// tool for code-generator run  
$ flutter pub add --dev build_runner
// code generator
$ flutter pub add --dev freezed
// freezed를 위한 annotations contains packages !!
// 만약 json_serializable:이 필요하면 pubspec.yaml에 dev_dependencies에 추가

flutter pub run build_runner build을 이용해서 파일 빌드를 해서 자동으로 freezed 파일이 만들어지게 해줌! (import 이용)

변경 시에도 flutter pub run build_runner build를 이용해서 재빌드 시키면 됌


model 만들기
(import 'package:flutter/foundation.dart'를 이용해서 flutter devtool에서 객체를 잘 읽을 수 있게 해주니 나쁘지 않음!!)

예시를 통해 이해해보기


import 'package:freezed_annotation/freezed_annotation.dart';

part 'person.freezed.dart';

// 꼴랑 이코드만 추가함
 // freezed 선언
class Person with _$Person {
// mixin을 이용하여 객체의 다양한 속성/메소드 정의
  //(2)

  ('name.isNotEmpty', 'name cannot be empty')
  // validation을 위해 쓰임  / 앞의 것이 허용되지 않으면 뒤에 에러가 나옴
  ('age >= 0')
  factory Person({
  // factory로 선언 / 따른 모델처럼 final로 위의 선언하지 않아도 문제 x
  // 생성자 정의시 표시된 대로 키워드 사용(const로 만들어도 되긴함..)
  
    required int id,
    required String name,
    required int age,
    required Group group,
  }) = _Person;

  // factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
  // json으로도 만들 수 있음! 

  const Person._();
  // 밑의 get과 hello를 쓰기 위해  사용함 / 그리고 코드에 오류가 발생하기에 다시 build를 해줘야함
  // define a private empty constructor:

  get nameLength => this.name.length;

  void hello() {
    print("123");
  }
}

변경 가능한 속성을 정의하고 싶다면, @unfreezed를 사용



class Person with _$Person {
  factory Person({
    required String firstName,
    required String lastName,
    required final int age,
  }) = _Person;

  factory Person.fromJson(Map<String, Object?> json)
      => _$PersonFromJson(json);
}

void main() {
  var person = Person(firstName: 'John', lastName: 'Smith', age: 42);

  person.firstName = 'Mona';
  person.lastName = 'Lisa';
}
// age속성을 으로 명시적으로 표시했기 때문에 여전히 변경할 수 없습니다 final.

// Person더 이상 사용자 정의 ==/hashCode 구현이 없습니다.

이제 이부분은 ui에 적용해보겠습니다.

    final schoolOne = School(id: 3, name: 'MIT');
    final groupOne =
        Group(id: 2, name: 'Flutter Development', school: schoolOne);
    final personOne = Person(id: 1, name: 'sunny', age: 29, group: groupOne);

    final personNew = personOne.copyWith(
      group: groupOne.copyWith(
        school: schoolOne.copyWith(
          name: 'Yale',
        ),
      ),
    );
    final personNewTwo = personOne.copyWith.group.school(name: 'Harvard');

    final personTwo = Person(id: 1, name: 'sunny', age: 29, group: groupOne);
    final personThree = Person(
        id: personOne.id, name: personOne.name, age: 18, group: groupOne);
    final personFour = personOne.copyWith(age: 18);

    // personOne.hello();
    
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: true,
        title: const Text("freezed test"),
        centerTitle: true,
      ),
      body: SafeArea(
        child: SingleChildScrollView(
          child: Container(
            padding: const EdgeInsets.only(left: 10, right: 10),
            child: Column(
              children: [
                renderText('person1.id', personOne.id.toString()),
                renderText('person1.name', personOne.name),
                renderText('person1.age', personOne.age.toString()),
                renderText('toString()', personOne.toString()),
                // renderText('toJson()', personOne.toJson().toString()),
                renderText('==', (personOne == personTwo).toString()),
                renderText('nameLength', personOne.nameLength.toString()),
                renderText('person4.ToString()', personFour.toString()),
                renderText('personNew.ToString()', personNew.toString()),
                renderText('personNewTwo.ToString()', personNewTwo.toString()),
              ],
            ),
          ),
        ),
      ),
    );
    
   renderText(String title, String text) {
    return Column(
      children: [
        Row(
          children: [
            Expanded(
              child: Text(
                title,
                style: const TextStyle(
                    fontSize: 20.0, fontWeight: FontWeight.bold),
              ),
            ),
          ],
        ),
        Row(
          children: [
            Expanded(
              child: Text(
                text,
                style: const TextStyle(fontSize: 20.0),
              ),
            ),
          ],
        ),
        const Divider(
          height: 1,
        ),
        const SizedBox(
          height: 10,
        )
      ],
    );
  }

위에 예제에서 copyWith 부터 설명하자면..

copyWth은 개체를 복사하는데 사용하며, 기존에 있던 값은 건드리지 않고 새로운 값만 변경시켜 사용함!
그렇지만 복잡한 개체에서 불편할 수 있기에 아래와 같은 코드를 씁니다.

Company company;

Company newCompany = company.copyWith(
  director: company.director.copyWith(
    assistant: company.director.assistant.copyWith(
      name: 'John Smith',
    ),
  ),
);
profile
즐거움을 만드는 사람

0개의 댓글