Skip to main content

7 posts tagged with "dart"

View All Tags

· 3 min read
Park Ki Hyun

factory Constructor


factory constructor의 constructor redirection에 대해 알고 있어야 한다. 그리고 const를 사용할 수 있음.

필요한 패키지


freezed_annotation: dep : 코드 생성기에 대한 어노테이션 패키지

build_runner : dev-dep : 코드 생성기 실행

freezed : dev-dep : 코드 생성기

json_annotation : dep : 코드 생성기인 json_serializable의 어노테이션 갖고 있는 패키지

json_serializable : dev-dep : 코드 생성기

freezed와 json_serializable 사용할 경우

analysis_options.yaml에 설정

analyzer:
errors:
invalid_annotation_target: ignore
exclude:
- '**/*.freezed.dart'
- '**/*.g.dart'

build runner를 사용해서 코드 gen하려면

dart run build_runner build [--delete-conflicting-outputs]

or

dart run build_runner watch [-d]

build는 one-time, watch는 계속 빌드함

watch가 빌드 타임 적다.

[]에 있는 옵션은 previous build에서 발생한 것 건너뛰기

extension

freezed라는 확장 설치해야 한다.

ptf : part '.freezed.dart'; 생성 pts : part '.g.dart'; 생성 fdataclass : Dataclass 생성 funion : Union class 생성

기능


정리

우선 다양한 것들을 override해준다.

toString이나 copyWith, equality 등을 오버라이딩 해줌.

copyWith

일반적인 copyWith + null도 지원해줌

deep copyWith도 제공해준다. 복잡한 코드를 간단하게 작성할 수 있도록 지원

Json annotation

(name: 'parking_lot_capacity') int? parkingLotcapacity,

data class를 만들 때 이런 인자값을 볼 수 있다.

변수 parkingLotcapacity를 json키 값 'parking_lot_capacity'로 판단하겠다는 뜻이다.

  factory Hotel.fromJson(Map<String, dynamic> json) => _$HotelFromJson(json);

이런 것도 제공해준다.

Provider


위젯이나 다른 Provider에 값을 제공

riverpod에서는 Provider를 watch할 수 있다. 그리고 그냥 값을 제공하는 Provider다.

dep

equatable,flutter_riverpod,riverpod_annotation

dev-dep

build_runner,custom_lint,flutter_lints,riverpod_generator, riverpod_lint

· 2 min read
Park Ki Hyun

Equatable


dart class generator라는 vs code extension을 사용할 때 객체 비교를 위해서 equatable이라는 dart 패키지를 이용할 수 있습니다.

vs code preferences에서 equatable 관련 설정을 true로 변경한다면 generator를 이용할 수 있습니다.

함수를 통해 객체를 생성하면 주소 값이 달라져서 같은 값을 갖고 있는 객체를 비교해도 false로 나오는데 equatable을 이용해서 비교하면 true를 반환할 수 있습니다.

Json 관련


json object로 자동 data class가 생성되는 마법이 있다고 합니다.

  1. 일단 dart 파일을 만듭니다.

  2. api 응답 json 값을 넣습니다.

  3. ctrl+shift+p해서 Generate from JSON 입력해서 선택

  4. class 이름 입력

  5. no 선택

그럼 data class 자동 생성 해준다.

fromMap, toMap만 잘 확인해보면 된다. (beta 단계임)

· One min read
Park Ki Hyun

Treeview


이 라이브러리를 사용한다.

animated_tree_view다.

TreeNode.root..addAll([]) 해서 배열을 넣을 수 있다.

  final myTree = TreeNode.root()
..addAll([
TreeNode(key: "Today"),
TreeNode(key: "Tomorrow")
..addAll([
TreeNode(key: "task 1"),
TreeNode(key: "task 2"),
TreeNode(key: "task 3"),
]),
TreeNode(key: "Upcoming"),
]);

TreeView.simple을 사용해봤는데 builder에서 인자로 context, node를 받는다.

주의할 점은 key로 하기 때문에 key 중복되지 않게 조심해야한다. 같은 level만 아니면 괜찮다. (같은 level아니면 이름 중복 가능)

· One min read
Park Ki Hyun

Future.wait


  Future<void> searchProductList() async {
isBusy = true;
final results = await Future.wait([
productRepository.searchProductList(keyword),
Future.delayed(const Duration(milliseconds: 555)),
]);
productList = results[0];
isBusy = false;
}

Future.wait이라는게 있는데 안에 있는 Future wait의 배열 명령어들이 모두 끝날 때까지 기다림

즉 위 코드 상으로는 search하는거와 delayed를 동시에 돌리는데 555 millisecond는 무조건 돌고 그 이상은 search끝날 때까지 기다린다는 뜻

· 3 min read
Park Ki Hyun

ClipRRect


container를 border radius하게 디자인 했는데 스크롤 바가 오버플로우 되는 현상이 있었다.

ClipRRect로 스크롤바를 만드는 listview 위젯을 감싸니 오버플로우 되는 부분은 안보이게 됐다.

ClipRRect위젯은 클리핑하는 위젯인데 클리핑이란 주어진 경계 내에서만 내용을 보여주고 경계 넘어서는 잘라내는 것을 의미한다고 한다.

주로 이미지를 둥근 액자에 넣고 싶을 때도 사용한다고 한다..

listView


사실 바보같은 짓을 했다 listView 안에 expanded를 넣으려고 했다. 왜냐하면 width를 double.infinity하게 하고싶었었다. 그러나 listView를 잘 몰랐었다.

listView의 자식들은 listView의 크기를 따라간다. 그래서 listView를 Expanded안에 infinity로 두면 그 안에도 infinity다. 그렇게 해결했다.

GestureDetector의 behavior


tip

deferToChild: 자식 중 하나가 적중 시 이벤트 수신(투명한 대상 이벤트 수신 x)
translucent : 반투명한 대상 & 시각적으로 뒤에 있는 대상도 이벤트 수신
opaque : 시각적으로 뒤에 있는 대상은 이벤트 수신 불가능

behavior: HitTestBehavior.translucent,

이와 같이 사용한다면 패딩부분도 클릭한다면 이벤트 수신될 수 있다.

Divider


ListView.separated를 사용하여 separatorBuilder를 통해 구분자를 넣을 수 있었다.

줄을 긋고 싶었는데 Divider를 사용할 수 있었다.

height로 상하 여백을 정할 수 있었고
thickness로 줄의 굵기를
indent,endIndent로 좌우 여백을
color로 색상을 정할 수 있었다.

리랜더링


다국어 지원 설정을 했는데 값은 변경 됐는데 화면 리랜더링을 못해서 계속 애먹었었다. 결국에는 riverpod provider를 수정하여 다국어도 watch하는 방법으로 변경했는데 현업에서 이렇게 사용하는지는 아직 모르겠다..

· 2 min read
Park Ki Hyun

nullable constructor


실수한 코드

처음에 class의 인스턴스를 만들 때 nullable로 선언하면 될 줄 알았다.

class NaviState {
final int? index;
final bool? yesOrNo;

NaviState({
this.index,
this.yesOrNo,
});
}

이렇게 했더니 사용하는 변수 타입이 nullabe이 되어버려서 계속 사용하는 변수 뒤에 !를 붙여줘서 null이 아님을 명시했어야 했는데

원했던 코드

class NaviState {
final int index;
final bool yesOrNo;

NaviState({
int? index,
bool? yesOrNo,
}) : index = index ?? 0,
yesOrNo = yesOrNo ?? false;
}

이렇게 nullable로 선언하는 것이 아닌 생성자에서 nullable로 받고 null인 경우 초기값을 설정하도록 하는 것이 내가 의도한 방향성과 더 맞는 코드인 것을 알게 됐다.


flutter에서 라우팅 하는 방법은 좀 다양한 것 같다.

그 중 Navigator.pushNamed이다.

Navigator.pushNamed로 context에 불러올 위젯 이름을 push한다.

그러면 정의해 놓은 onGenerateRoute를 통해서 page를 불러오면 된다. 간단하다.

GestureDetector 렌더링 문제


갑자기 GestureDetector만 사용하면 렌더링 에러가 났다.

GestureDetector에 사이즈를 제공해주지 않았기 때문이라고 한다. (ListView도 마찬가지다)

Expanded(
child: SizedBox(
height: 200,
width: 200,
child: GestureDetector(),
),
)

이런식으로 구현할 수 있다.

· 3 min read
Park Ki Hyun

선택적 매개변수


Color getColor(WidgetRef ref, bool isInactive, [Color? color]) {}

위와 같은 함수가 있다고 가정하자. [Color? color] 이렇게 대괄호로 받는 매개변수는 넣어도 되고 안 넣어도 되는 선택적 매개변수이다.

svg icon에 대해서


지금 저는 IconButton을 사용하지 않고 Custom으로 Button위젯을 만들어서 사용하고 있습니다.

이 때 버튼 등 다양한 값들을 GestureDetectorRow 위젯으로 감싸아서 했는데 width가 넘어갔다는고 하네요.. 그래서 appbar가 좀 밀려보였습니다.

svg파일의 크기를 줄여야 합니다. vs code에서 위젯트리 디버깅 확인해보며 Row에 할당된 width를 확인하고 그 이하로 svg 파일 크기를 줄이면 해결됩니다.


navigationRail을 사용하면 사이드 네비게이션 바를 사용할 수 있다.

NavigationRail안에 NavigationRailDestination으로 Navigator를 하나하나 정의할 수 있다.

selectedIndex가 필수로 필요하다.

onDestinationSelected로 어떤 것을 선택했는지 정의할 수 있다. setState로도 할 수 있는데 provider를 사용해서 watch해서 사용할 수도 있다.

예를 들어서 selectedIndex를 state를 watch하고 onDestinationSelected에는 값을 바꿔주는 함수를 정의해서 read로 호출하면 될 듯

selectedIconThemeunselectedIconTheme을 통하여 테마 지정 가능 아직은 큰 필요성 모르겠다.

trailing을 사용하면 맨 밑에 버튼 같은 걸 만들 수 있습니다.

이 과정도 복잡했는데 Expanded와 Align 을 사용해야 할 수 있었습니다. 이에 대해서는 또 찾아봐야겠네요

body에 border-radius


사실 body에 border-radius줘도 안바뀐다 왜냐하면 배경색과 색이 같아서

그래서 body를 이루고 있는 Row위젯을 ColorBox로 감쌉니다. 그렇게 배경색을 주고 밑에서 Container에 해당했던 부분(기존에 border-radius를 줬던 부분)을 Expanded로 확장시킵니다 그럼 끝 !