ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [개발일지] flutter 앱개발 3주차
    Study/Development 2022. 9. 23. 16:57

    <스파르타코딩 flutter 강의 수강일지>

     

    3주차: 패키지 사용법 익히기 & 앱 기능 만들기

    1. Flutter 패키지 관련 사이트

    Pub.dev

    플러터 패키지를 모아둔 사이트

    https://pub.dev/

     

     

    Dart packages

    Pub is the package manager for the Dart programming language, containing reusable libraries & packages for Flutter, AngularDart, and general Dart programs.

    pub.dev

     

    Awsome Flutter

    Flutter에 관련된 모든 자료를 모아둔 Github 문서

    https://github.com/Solido/awesome-flutter#ui

     

    GitHub - Solido/awesome-flutter: An awesome list that curates the best Flutter libraries, tools, tutorials, articles and more.

    An awesome list that curates the best Flutter libraries, tools, tutorials, articles and more. - GitHub - Solido/awesome-flutter: An awesome list that curates the best Flutter libraries, tools, tuto...

    github.com

     

    Flutter Gems

    카테고리별 플러터 패키지 추천

    https://fluttergems.dev/

     

    Flutter Gems - A Curated List of Dart & Flutter packages

    Flutter Gems is a curated list of Dart & Flutter packages that are categorized based on functionality. Flutter Gems is also a visual alternative to pub.dev

    fluttergems.dev

     

    2. 패키지 설치하는 법(Terminal)

    flutter pub add <설치하려는 패키지 이름>

     

    *설치해본 패키지들

    • introduction_screen : 온보딩 화면 패키지
    • google_fonts : 폰트 패키지
    • table_calendar : 달력 위젯
    • provider : 상태 관리
    • intl : DateTime 형식 지정
    • shared_preferences : 데이터 저장

     

    3. Onboarding Page

    3페이지짜리 온보딩 페이지 기본 뼈대

    body: IntroductionScreen(
            pages: [
              // 페이지1
              PageViewModel(
                title: "Title1",
                bodyWidget: Text("body1"),
              ),
    
              // 페이지2
              PageViewModel(
                title: "Title2",
                bodyWidget: Text("body2"),
              ),
            ],
            next: Text("Next", style: TextStyle(fontWeight: FontWeight.w600)),
            done: Text("Done", style: TextStyle(fontWeight: FontWeight.w600)),
            onDone: () {
              // When done button is press
            },
          ),

     

     

    4. 기본 데이터 처리 기능 CRUD

    • Create
    • Read
    • Update
    • Delete

    Provider Package 이용한 CRUD 샘플

      /// Diary 목록
      List<Diary> diaryList = [];
    
      /// 특정 날짜의 diary 조회
      List<Diary> getByDate(DateTime date) {
        return diaryList
            .where((diary) => isSameDay(date, diary.createdAt))
            .toList();
      }
    
      /// Diary 작성
      void create(String text, DateTime selectedDate) {
        DateTime now = DateTime.now();
    
        DateTime createdAt = DateTime(
          selectedDate.year,
          selectedDate.month,
          selectedDate.day,
          now.hour,
          now.minute,
          now.second,
        );
    
        Diary diary = Diary(
          text: text,
          createdAt: createdAt,
        );
    
        diaryList.add(diary);
        notifyListeners();
      }
    
      /// Diary 수정
      void update(DateTime createdAt, String newContent) {
        Diary diary =
            diaryList.firstWhere(((diary) => diary.createdAt == createdAt));
        diary.text = newContent;
        notifyListeners();
      }
    
      /// Diary 삭제
      void delete(DateTime createdAt) {
        diaryList.removeWhere((diary) => diary.createdAt == createdAt);
    
        notifyListeners();
      }

     

    5. SharedPreferences에 커스텀 클래스를 저장

     

    커스텀 클래스 → Map → jsonString → Map → 커스텀 클래스 변환

     

    import 'dart:convert';
    
    void main() {
      Diary diary = Diary("오늘 일기", DateTime.now());
      
      // 1) Diary ➡ Map
      Map<String, dynamic> map = diary.toJson();
      print("1) Diary ➡ Map : $map");
      
      // 2) Map ➡ jsonString
      String jsonString = jsonEncode(map);
      print("2) Map ➡ jsonString : $jsonString");
      
      // 3) jsonString ➡ Map
      Map<String, dynamic> jsonMap = jsonDecode(jsonString);
      print("3) jsonString ➡ Map : $jsonMap");
      
      // 4) Map ➡ Diary
      Diary parsedDiary = Diary.fromJson(jsonMap);
      print("4) Map ➡ Diary : $parsedDiary");
    }
    
    class Diary{
      String text;
      DateTime createdAt;
      
      Diary(this.text, this.createdAt);
     
      // Diary -> Map
      Map<String, dynamic> toJson() {
        return {
          "text": text,
          "createdAt": createdAt.toString(),
        };
      }
      
      // Map -> Diary
      factory Diary.fromJson(Map<String, dynamic> json) {
        return Diary(
          json["text"],
          DateTime.parse(json["createdAt"]),
        );
      }
    }

     

    실습과제에 사용한 코드

    void main() async {
      // 메인 함수에 추가하여야 할 코드
      WidgetsFlutterBinding.ensureInitialized();
      SharedPreferences prefs = await SharedPreferences.getInstance();
      runApp(
        MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (context) => DiaryService(prefs)),
          ],
          child: const MyApp(),
        ),
      );
    }
    import 'dart:convert';
    import 'dart:developer';
    
    import 'package:flutter/material.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    import 'package:table_calendar/table_calendar.dart';
    
    class Diary {
      String text; // 내용
      DateTime createdAt; // 작성 시간
    
      Diary({
        required this.text,
        required this.createdAt,
      });
    
      Map<String, dynamic> toJson() {
        return {"text": text, "createdAt": createdAt.toString()};
      }
    
      factory Diary.fromJson(Map<String, dynamic> jsonMap) {
        return Diary(
            text: jsonMap['text'], createdAt: DateTime.parse(jsonMap['createdAt']));
      }
    }
    
    class DiaryService extends ChangeNotifier {
      SharedPreferences prefs;
      DiaryService(this.prefs) {
        List<String> stringDiaryList = prefs.getStringList('diaryList') ?? [];
        for (String stringDiary in stringDiaryList) {
          // stringDiary ==> Diary
          Map<String, dynamic> jsonMap = jsonDecode(stringDiary);
          Diary diary = Diary.fromJson(jsonMap);
          diaryList.add(diary);
        }
      }
    
      /// Diary 목록
      List<Diary> diaryList = [];
    
      /// 특정 날짜의 diary 조회
      List<Diary> getByDate(DateTime date) {
        return diaryList
            .where((diary) => isSameDay(date, diary.createdAt))
            .toList();
      }
    
      /// Diary 작성
      void create(String text, DateTime selectedDate) {
        DateTime now = DateTime.now();
    
        DateTime createdAt = DateTime(
          selectedDate.year,
          selectedDate.month,
          selectedDate.day,
          now.hour,
          now.minute,
          now.second,
        );
    
        Diary diary = Diary(
          text: text,
          createdAt: createdAt,
        );
    
        diaryList.add(diary);
        print(inspect(diary));
        notifyListeners();
        _saveDiaryList();
      }
    
      /// Diary 수정
      void update(DateTime createdAt, String newContent) {
        Diary diary =
            diaryList.firstWhere(((diary) => diary.createdAt == createdAt));
        diary.text = newContent;
        notifyListeners();
        _saveDiaryList();
      }
    
      /// Diary 삭제
      void delete(DateTime createdAt) {
        diaryList.removeWhere((diary) => diary.createdAt == createdAt);
    
        notifyListeners();
        _saveDiaryList();
      }
    
      /// Diary prefs 저장
      void _saveDiaryList() {
        List<String> stringDiaryList = [];
    
        for (Diary diary in diaryList) {
          Map<String, dynamic> jsonMap = diary.toJson();
          String stringDiary = jsonEncode(jsonMap);
          stringDiaryList.add(stringDiary);
        }
    
        prefs.setStringList('diaryList', stringDiaryList);
      }
    }

     

    알아둬야 할 것들

    1. Where() 메소드

    where()

    배열 요소를 필터링한다.

    final numbers = <int>[1, 2, 3, 5, 6, 7];
    
    // 5보다 작은 요소 반환
    var result = numbers.where((x) => x < 5); // (1, 2, 3)
    
    // 5보다 큰 요소 반환
    result = numbers.where((x) => x > 5); // (6, 7)
    
    // 짝수 반환
    result = numbers.where((x) => x.isEven); // (2, 6)

     

    firstWhere()

    요소를 반복하고 주어진 조건의 첫번째 요소를 반환한다.

    *lastWhere(): 마지막 요소 반환

    // 6으로 나눴을 때, 나머지가 0인 것 반환
    var result = await Stream.fromIterable([1, 3, 4, 9, 12])
        .firstWhere((element) => element % 6 == 0, orElse: () => -1);
    print(result); // 12
    
    // 찾고자 하는 값이 없을 때
    result = await Stream.fromIterable([1, 2, 3, 4, 5])
        .firstWhere((element) => element % 6 == 0, orElse: () => -1);
    print(result); // -1

     

    removeWhere()

    주어진 조건에 맞는 모든 요소를 제거

    final numbers = <String>['one', 'two', 'three', 'four'];
    
    // 글자수가 3인 요소 제거
    numbers.removeWhere((item) => item.length == 3);
    print(numbers); // [three, four]

     

     

    2. Null Safety

    e1!       // e1이 null 인 경우 에러 발생
    e2 ?? e3  // e2가 null 일 경우 e3을 사용
    x ??= e4  // x가 null 일 경우 `x = e4`.
    e5?.foo() // e5가 null이 아니면, e5에 `foo`함수 실행
    [...? e6] // e6이 null이 아니면, e6을 list로 spread하여 확장

     

     

     

    오류 탐험

    DateTime을 받아올 때, 순서를 잘못넣어서 오류가 생겼다.

    day 데이터가 year자리에 들어간 것 때문에, 계속 화면에 나타나지 않았었다.

    순서에 유의하도록 해야겠다.

     

    커스텀 클래스의 인스턴스 내용을 살펴  inspect()를 사용한다.

    print(inspect(diary));
    반응형

    댓글

© 2023. titann all rights reserved