커뮤니티
포인트
쿠폰
내 강의실
국비 신청 내역
증명서
계정
로그아웃
학습 질문
개발 일지
나의 활동
답변 완료
핀 정렬 문의
[왕초보] 플러터(Flutter)로 시작하는 앱개발 종합반 v0
3주차
북마크
진*만
댓글
3
추천
0
조회수
11
조회수
11
답변 완료

* 겪고 있는 문제 상황을 최대한 자세하게 작성해주세요.

* 문제 해결을 위해 어떤 시도를 해보았는지 구체적으로 함께 알려주세요.


질문 내용

안녕하세요. 핀 메모 수정 함수에서 정렬 부분 설명 부탁 드립니다. 저는 updateMemo(메모 수정 함수)에서 

a.pinYn.compareTo(b.pinYn) 사용해서 개발을 했는데 updatePinMemo(핀 메모 수정 함수)에서

정렬 부분은 이해하기가 힘듭니다.


확인 부탁 드립니다.

감사합니다.

----------------------------------------------------------------------------------------------------------

 

 // 핀 메모 수정 함수 호출

 updatePinMemo({required int index}) {

  Memo memo = memoList[index];

  memo.isPinned = !memo.isPinned; // 핀 체크 여부

  memoList = [...memoList.where((element) => element.isPinned), ...memoList.where((element) => !element.isPinned)]; // 정렬 부분 @@@@ ■■■■■■

  notifyListeners(); // Consumer<MemoService>의 builder 부분을 호출해서 화면 새로 고침

  saveMemoList(); // 메모 저장 함수 호출

 }


----------------------------------------------------------------------------------------------------------

 

 // 메모 수정 함수

 updateMemo({required int index, required String pinYn, content}) {

  debugPrint("■ [/MemoService.C] [updateMemo()] ==> [T_01] [메모 수정 함수]");


  var now = new DateTime.now(); //반드시 다른 함수에서 해야함, Mypage같은 클래스에서는 사용 불가능

  String editTime = DateFormat('yyyy-MM-dd HH:mm:ss').format(now); // 메모 수정 시간(현재 시간)

  debugPrint("■ [/MemoService.C] [updateMemo()] ==> [T_03] [index]" + index.toString() + "[메모 내용]" + content + "[메모 수정 시간]" + editTime + "[sPinYn]" + pinYn);


  Memo memo = memoList[index]; // 메모 List

  memo.pinYn = pinYn; // 핀 여부

  memo.content = content; // 메모 내용

  memo.editTime = editTime; // 메모 수정 시간

  debugPrint("■ [/MemoService.C] [updateMemo()] ==> [T_23] [index]" + index.toString() + "[메모 내용]" + content + "[메모 수정 시간]" + editTime + "[sPinYn]" + pinYn);


  notifyListeners(); // Consumer<MemoService>의 builder 부분을 호출해서 화면 새로 고침


  saveMemoList(); // 메모 저장 함수 호출


  memoList.sort((b, a) => a.pinYn.compareTo(b.pinYn)); // 핀 아이콘별 리스트 정렬(sort) / / 정렬 부분 @@@@ ■■■■■■

  debugPrint("■ [/MemoService.C] [updateMemo()] ==> [T_91] [index]" + index.toString() + "[메모 내용]" + content + "[메모 수정 시간]" + editTime + "[sPinYn]" + pinYn);


  notifyListeners(); // Consumer<MemoService>의 builder 부분을 호출해서 화면 새로 고침

 }

==============================================================================================================

 

- flutter/dart sort 간단한 설명 / List 정렬하기 TIL # 46

https://daldalhanstory.tistory.com/246

==============================================================================================================





스파르타 즉문즉답


작성한 코드 및 에러 메세지

 

 

 - /main.dart 파일에서 @@@

import 'package:flutter/cupertino.dart';

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

import 'package:shared_preferences/shared_preferences.dart';


import 'memo_service.dart';


late SharedPreferences prefs; // shared_preferences 패키지(기기에 파일로 저장)


void main() async {

 debugPrint("■ [/main.dart] [main()] ==> [T_01] [Project Start] ■■■");


 WidgetsFlutterBinding.ensureInitialized();

 prefs = await SharedPreferences.getInstance(); // 인스턴스 생성(shared_preferences 패키지)


 runApp(

  MultiProvider(

   providers: [

    // providers 패키지(상태 관리)

    ChangeNotifierProvider(create: (context) => MemoService()), // Memo 데이터 관리 class 호출

   ],

   child: const MyApp(), // MyApp class 호출

  ),

 );

}


/**

 * @description HomePage class(00. MyA pp)

*/

class MyApp extends StatelessWidget {

 const MyApp({super.key});


 @override

 Widget build(BuildContext context) {

  debugPrint("■ [/MyApp.C] [build()] ==> [T_01] [MyApp Start] ■");


  return MaterialApp(

   debugShowCheckedModeBanner: false,

   home: HomePage(), // 홈 페이지 호출

  );

 }

}


/**

 * @description HomePage class(01. 홈 페이지)

*/

class HomePage extends StatefulWidget {

 const HomePage({super.key});


 @override

 State<HomePage> createState() => _HomePageState();

}


/**

 * @description _HomePageState class(01-2. 홈 페이지 Stateful Widget)

*/

class _HomePageState extends State<HomePage> {

 @override

 Widget build(BuildContext context) {

  debugPrint("■ [/_HomePageState.C] [build()] ==> [T_01] [HomePage Start] ■");


  return Consumer<MemoService>(

   builder: (context, memoService, child) {

    debugPrint("■ [/_HomePageState.C] [build()] ==> [T_20]");


    // memoService로 부터 memoList 가져오기

    List<Memo> memoList = memoService.memoList;

    debugPrint("■ [/_HomePageState.C] [build()] ==> [T_22] [memomemoList_총수]" + memoService.memoList.length.toString());


    return Scaffold(

     appBar: AppBar(

      // 01. appBar 위젯■ =====================>

      title: Text("mymemo"),

     ), // 01. appBar 위젯■ =====================>

     body: memoList.isEmpty

       ? Center(child: Text("메모를 작성해 주세요"))

       : ListView.builder(

         // 01-1. 메모 리스트 ListView

         itemCount: memoList.length, // memoList 개수 만큼 보여주기

         itemBuilder: (context, index) {

          Memo memo = memoList[index]; // index에 해당하는 memo 가져오기


          return ListTile(

           // ListTile

           leading: IconButton(

            // 메모 고정 아이콘

            icon: Icon(memo.isPinned ? CupertinoIcons.pin_fill : CupertinoIcons.pin),

            onPressed: () {

             // 핀 Icon 클릭 이벤트

             debugPrint("■ [/_HomePageState.C] [==> [T_61] [핀 Icon 클릭 이벤트]");

             debugPrint("■ [/_HomePageState.C] [==> [T_62] [i_번째]" + index.toString() + "[메모 내용]" + memo.content);


             memoService.updatePinMemo(index: index); // 핀 메모 수정 함수 호출

            },

           ),

           // 메모 내용 (최대 3줄까지만 보여주도록)

           title: Text(

            memo.content,

            maxLines: 3,

            overflow: TextOverflow.ellipsis,

           ),

           trailing: Text(memo.updatedAt == null ? "" : memo.updatedAt.toString().substring(0, 19)), // 03. 메모 수정 시간 Text

           onTap: () async {

            // 51. onTap(메모 내용 Text 클릭 이벤트)

            await Navigator.push(

             context,

             MaterialPageRoute(

              builder: (_) => DetailPage(

               // 메모 생성 및 수정 페이지로 이동

               index: index,

              ),

             ),

            );

            // 해당 메모 내용이 비어 있으면(해당 메모가 삭제 처리)

            debugPrint("■ [/_HomePageState.C] [==> [T_80_2] [메모 내용]" + memo.content);


            if (memo.content.isEmpty) {

             // 메모 내용이 널 이면

             debugPrint("■ [/_HomePageState.C] [==> [T_82] [메모 삭제 함수 호출]");

             memoService.deleteMemo(index: index); // 메모 삭제 함수 호출

            }

           },

          );

         },

        ),

     floatingActionButton: FloatingActionButton(

      // 51. floating ActionButton 위젯■ =====================>


      child: Icon(Icons.add),

      onPressed: () async {

       // + 버튼 클릭시 메모 생성 및 수정 페이지로 이동

       memoService.createMemo(content: ''); // 메모 생성 함수 호출

       await Navigator.push(

        context,

        MaterialPageRoute(

         builder: (_) => DetailPage(

          index: memoService.memoList.length - 1,

         ),

        ),

       );

       // 해당 메모 내용이 비어 있으면(해당 메모가 삭제 처리)

       debugPrint("■ [/_HomePageState.C] [==> [T_90] [해당 메모 내용이 비어 있으면]");


       if (memoList[memoService.memoList.length - 1].content.isEmpty) {

        // 메모 내용이 널 이면

        debugPrint("■ [/_HomePageState.C] [==> [T_95] [빈 메모 삭제 함수 호출]");

        memoService.deleteMemo(index: memoList.length - 1);

        ; // 메모 삭제 함수 호출

       }

      },

     ), // 51. floating ActionButton 위젯■ =====================>

    );

   },

  );

 }

}


/**

 * @description 메모 생성 및 수정 페이지 class(02. 상세 페이지)

*/

class DetailPage extends StatelessWidget {

 DetailPage({super.key, required this.index});


 final int index;


 TextEditingController contentController = TextEditingController();


 @override

 Widget build(BuildContext context) {

  debugPrint("■ [/DetailPage.C] ==> [T_01] [메모 상세 페이지 Start] ■");

  debugPrint("■ [/DetailPage.C] ==> [T_02] [index]" + index.toString());


  MemoService memoService = context.read<MemoService>(); // context.read<(1회성으로 클래스 접근할 때 사용(화면 새로고침이 필요 없을 때))

  Memo memo = memoService.memoList[index];


  contentController.text = memo.content; // 메모 내용


  return Scaffold(

   appBar: AppBar(

    // 01. appBar 위젯■ =====================>

    actions: [

     IconButton(

      onPressed: () {

       debugPrint("■ [/DetailPage.C] ==> [T_21] [삭제 버튼 클릭 이벤트]");

       // 삭제 버튼 클릭시

       showDeleteDialog(context, memoService);

      },

      icon: Icon(Icons.delete),

     )

    ],

   ), // 01. appBar 위젯■ =====================>

   body: Padding(

    // 02. body 위젯■ ==================================>

    padding: const EdgeInsets.all(16),

    child: TextField(

     controller: contentController,

     decoration: InputDecoration(

      hintText: "메모를 입력하세요",

      border: InputBorder.none,

     ),

     autofocus: true,

     maxLines: null,

     expands: true,

     keyboardType: TextInputType.multiline,

     onChanged: (value) {

      // 텍스트필드 안의 값이 변할 때

      memoService.updateMemo(index: index, content: value); // 메모 수정 함수 호출

     },

    ),

   ), // 02. body 위젯■ ==================================>

  );

 }


/**

 * @description 삭제 Dialog class

*/

 void showDeleteDialog(BuildContext context, MemoService memoService) {

  showDialog(

   context: context,

   builder: (context) {

    return AlertDialog(

     title: Text("정말로 삭제하시겠습니까?"),

     actions: [

      // 취소 버튼

      TextButton(

       onPressed: () {

        Navigator.pop(context);

       },

       child: Text("취소"),

      ),

      // 확인 버튼

      TextButton(

       onPressed: () {

        debugPrint("■ [/DetailPage.C] ==> [T_41] [확인 버튼 클릭 이벤트] [index]" + index.toString());


        memoService.deleteMemo(index: index); // 메모 삭제 함수 호출

        Navigator.pop(context); // 팝업 닫기

        Navigator.pop(context); // HomePage 로 가기

       },

       child: Text(

        "확인",

        style: TextStyle(color: Colors.pink),

       ),

      ),

     ],

    );

   },

  );

 }

=============================================================================================================



- /memo_service.dart 파일에서 @@@

iimport 'dart:convert';


import 'package:flutter/material.dart';


import 'main.dart';


/**

 * Memo 데이터 class

 * Memo 데이터의 형식을 정해줍니다. 추후 isPinned, updatedAt 등의 정보도 저장할 수 있습니다.

*/

class Memo {

 Memo({

  required this.content, // 메모 내용

  this.isPinned = false, // 핀 체크 여부

  this.updatedAt, // 메모 수정 시간

 });


 String content; // 메모 내용

 bool isPinned; // 핀 체크 여부

 DateTime? updatedAt; // 메모 수정 시간


 Map toJson() {

  return {

   'content': content, // 메모 내용

   'isPinned': isPinned, // 핀 체크 여부

   'updatedAt': updatedAt?.toIso8601String(), // 메모 수정 시간

  };

 }


 factory Memo.fromJson(json) {

  return Memo(

   content: json['content'], // 메모 내용

   isPinned: json['isPinned'] ?? false, // 핀 체크 여부

   updatedAt: json['updatedAt'] == null ? null : DateTime.parse(json['updatedAt']), // 메모 수정 시간

  );

 }

}


// Memo 데이터는 모두 여기서 관리

class MemoService extends ChangeNotifier {

 MemoService() {

  debugPrint("■ [/MemoService.C] [MemoService()] ==> [T_01] [Memo 데이터 관리 class(최초 실행시)]");


  loadMemoList();

 }


 List<Memo> memoList = [

  // 메모 List

  Memo(content: '장보기 목록: 사과, 양파'), // 더미(dummy) 데이터

  Memo(content: '새 메모'), // 더미(dummy) 데이터

 ];


 // 메모 생성 함수

 createMemo({required String content}) {

  debugPrint("■ [/MemoService.C] [createMemo()] ==> [T_01] [메모 생성 함수]");

  debugPrint("■ [/MemoService.C] [createMemo()] ==> [T_02] [메모 내용]" + content);

  debugPrint("■ [/MemoService.C] [createMemo()] ==> [T_03] [메모 수정 시간]" + DateTime.now().toString());


  Memo memo = Memo(content: content, updatedAt: DateTime.now());

  memoList.add(memo); // 메모 생성

  notifyListeners(); // Consumer<MemoService>의 builder 부분을 호출해서 화면 새로고침

  saveMemoList(); // 메모 저장 함수 호출

 }


 // 메모 수정 함수

 updateMemo({required int index, required String content}) {

  debugPrint("■ [/MemoService.C] [updateMemo()] ==> [T_01] [메모 수정 함수]");


  Memo memo = memoList[index]; // 메모 List

  memo.content = content; // 메모 내용

  memo.updatedAt = DateTime.now(); // 메모 수정 시간

  notifyListeners(); // Consumer<MemoService>의 builder 부분을 호출해서 화면 새로 고침

  saveMemoList(); // 메모 저장 함수 호출

 }


 // 핀 메모 수정 함수 호출

 updatePinMemo({required int index}) {

  Memo memo = memoList[index];

  memo.isPinned = !memo.isPinned; // 핀 체크 여부

  memoList = [...memoList.where((element) => element.isPinned), ...memoList.where((element) => !element.isPinned)]; // 정렬 @@@@

  notifyListeners(); // Consumer<MemoService>의 builder 부분을 호출해서 화면 새로 고침

  saveMemoList(); // 메모 저장 함수 호출

 }


 // 메모 삭제 함수

 deleteMemo({required int index}) {

  debugPrint("■ [/MemoService.C] [updateMemo()] ==> [T_01] [메모 삭제 함수]");

  debugPrint("■ [/MemoService.C] [updateMemo()] ==> [T_02] [메모 index]" + index.toString());


  memoList.removeAt(index); // index 메모 삭제

  notifyListeners(); // Consumer<MemoService>의 builder 부분을 호출해서 화면 새로 고침

  saveMemoList(); // 메모 저장 함수 호출

 }


 // 메모 저장 함수(기기에 파일로 저장)

 saveMemoList() {

  debugPrint("■ [/MemoService.C] [saveMemoList()] ==> [T_01] [메모 저장 함수]");


  List memoJsonList = memoList.map((memo) => memo.toJson()).toList();

  // [{"content": "1"}, {"content": "2"}]


  String jsonString = jsonEncode(memoJsonList);

  // '[{"content": "1"}, {"content": "2"}]'


  prefs.setString('memoList', jsonString);

 }


 // 메모 load 함수(기기에 파일로 저장)

 loadMemoList() {

  debugPrint("■ [/MemoService.C] [loadMemoList()] ==> [T_01] [메모 load 함수]");


  String? jsonString = prefs.getString('memoList');

  // '[{"content": "1"}, {"content": "2"}]'


  if (jsonString == null) return; // null 이면 로드하지 않음

  debugPrint("■ [/MemoService.C] [loadMemoList()] ==> [T_41] [jsonStringList로 변환_전(String)]" + jsonString);


  List memoJsonList = jsonDecode(jsonString);

  // [{"content": "1"}, {"content": "2"}]


  memoList = memoJsonList.map((json) => Memo.fromJson(json)).toList(); // String을 List로 변환

 }

}

=============================================================================================================

오류 발생 시, 작성한 코드 전체와 에러 메시지를 첨부해 주세요.

Tip 1) </> 아이콘을 눌러 코드박스를 만들어 보세요.

Tip 2) Ctrl+A(맥의 경우 Command+A) 단축키로 코드를 한 번에 선택할 수 있어요!



취소
 공유
취소
댓글 0
댓글 알림
나의얼굴