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

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

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



dart(expected_token) 이게 무슨 오류 일까요? 


스파르타 즉문즉답






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;


void main() async {

WidgetsFlutterBinding.ensureInitialized();

prefs = await SharedPreferences.getInstance();

runApp(

MultiProvider(

providers: [

ChangeNotifierProvider(create: (context) => MemoService()),

],

child: const MyApp(),

),

);

}


class MyApp extends StatelessWidget {

const MyApp({super.key});


@override

Widget build(BuildContext context) {

return MaterialApp(

debugShowCheckedModeBanner: false,

home: HomePage(),

);

}

}


// 홈 페이지

class HomePage extends StatefulWidget {

const HomePage({super.key});


@override

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

}


class _HomePageState extends State<HomePage> {

@override

Widget build(BuildContext context) {

return Consumer<MemoService>(

builder: (context, memoService, child) {

// memoService로 부터 memoList 가져오기

List<Memo> memoList = memoService.memoList;


return Scaffold(

appBar: AppBar(

title: Text("mymemo"),

),

body: memoList.isEmpty

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

: ListView.builder(

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

itemBuilder: (context, index) {

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

return ListTile(

// 메모 고정 아이콘

leading: IconButton(

icon: Icon(memo.isPinned

? CupertinoIcons.pin_fill

: CupertinoIcons.pin),

onPressed: () {

memoService.updatePinMemo(index: index);

},

),

// icon: Icon(CupertinoIcons.pin),

// onPressed: () {

// print('$memo : pin 클릭 됨');


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

title: Text(

memo.content,

maxLines: 3,

overflow: TextOverflow.ellipsis,

),

trailing: Text(memo.updatedAt == null

? ""

: memo.updatedAt.toString().substring(0, 19))

onTap: () {

// 아이템 클릭시

Navigator.push(

context,

MaterialPageRoute(

builder: (_) => DetailPage(

index: index,

),

),

); // 해당 메모가 비어있으면 삭제하는 로직

},

);

},

),

floatingActionButton: FloatingActionButton(

child: Icon(Icons.add),

onPressed: () {

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

memoService.createMemo(content: '');

Navigator.push(

context,

MaterialPageRoute(

builder: (_) => DetailPage(

index: memoService.memoList.length - 1,

),

),

); // 비어있으면 삭제

},

),

);

},

);

}

}


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

class DetailPage extends StatelessWidget {

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


final int index;


TextEditingController contentController = TextEditingController();


@override

Widget build(BuildContext context) {

MemoService memoService = context.read<MemoService>();

Memo memo = memoService.memoList[index];


contentController.text = memo.content;


return Scaffold(

appBar: AppBar(

actions: [

IconButton(

onPressed: () {

showDeleteDialog(context, memoService); // 삭제 버튼 클릭시

},

icon: Icon(Icons.delete),

),

],

),

body: Padding(

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);

},

),

),

);

}


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: () {

memoService.deleteMemo(index: index); // index에 해당하는 항목 삭제

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

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

},

child: Text(

"확인",

style: TextStyle(color: Colors.pink),

),

),

],

);

},

);

}

}






meon_service.dart


import 'dart:convert';


import 'package:flutter/material.dart';


import 'main.dart';


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

class Memo {

Memo({

required this.content,

this.isPinned = false,

this.updatedAt,

});


String content;

bool isPinned;

DateTime? updatedAt;


// get isPinned => bool;


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() {

loadMemoList();

}


List<Memo> memoList = [

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

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

];


get element => null;


createMemo({required String content}) {

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

memoList.add(memo);

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

saveMemoList();

}


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

Memo memo = memoList[index];

memo.content = content;

memo.updatedAt = DateTime.now();

notifyListeners();

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();

saveMemoList();

}


deleteMemo({required int index}) {

memoList.removeAt(index);

notifyListeners();

saveMemoList();

}


saveMemoList() {

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

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


String jsonString = jsonEncode(memoJsonList);

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


prefs.setString('memoList', jsonString);

}


loadMemoList() {

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

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


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


List memoJsonList = jsonDecode(jsonString);

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


memoList = memoJsonList.map((json) => Memo.fromJson(json)).toList();

}


// void updatePinMemo({required int index}) {}

}


// void saveMemoList() {}


// void updatePinMemo({required int index}) {}


// void deleteMemo({required int index}) {}



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