섹션 21. 캘린더 스케쥴러 오류 문의드립니다.
507
작성한 질문수 2
색상 상태관리 부분을 듣고 있습니다. 똑 같이 따라했는데요.
아래 내용과 같이 FutureBuilder를 사용하여 똑같이 따라 했는데도 불구하고 null이 리턴되어 오류가 납니다.
future: GetIt.I<LocalDatabase>().getCategoryColors() 에서 강사님 강의에서는 데이터를 가지고 오는데, 제가 만든 코드에서는 null이 리턴되네요. 혹시 몰라 main.dart에서 GetIt.I<LocalDatabase>().getCategoryColors() 를 실행해 보고, 결과를 보면 정상적인 데이터가 들어옵니다.
뭐가 문제일까요?
main.dart
import 'package:calendar_schedule_exam/database/drift_database.dart';
import 'package:calendar_schedule_exam/screen/home_screen.dart';
import 'package:drift/drift.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:intl/date_symbol_data_local.dart';
const DEFAULT_COLORS = [
// 빨강
'F44336',
// 주황
'FF9800',
// 노랑
'FFEB3B',
// 초록
'FCAF50',
// 파랑
'2196F3',
// 남
'3F51B5',
// 보라
'9C27B0',
];
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeDateFormatting();
final database = LocalDatabase();
GetIt.I.registerSingleton<LocalDatabase>(database);
final result = GetIt.I<LocalDatabase>().getCategoryColors();
final colors = await database.getCategoryColors();
if (colors.isEmpty) {
for (String hexCode in DEFAULT_COLORS) {
await database.createCategoryColor(
CategoryColorsCompanion(
hexCode: Value(hexCode),
),
);
}
}
runApp(MaterialApp(
theme: ThemeData(
fontFamily: 'NotoSans',
),
home: HomeScreen(),
));
}
schedule_bottom_sheet.dart
import 'package:calendar_schedule_exam/component/custom_text_field.dart';
import 'package:calendar_schedule_exam/const/colors.dart';
import 'package:calendar_schedule_exam/database/drift_database.dart';
import 'package:calendar_schedule_exam/model/category_color.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
class ScheduleBottomSheet extends StatefulWidget {
const ScheduleBottomSheet({super.key});
@override
State<ScheduleBottomSheet> createState() => _ScheduleBottomSheetState();
}
class _ScheduleBottomSheetState extends State<ScheduleBottomSheet> {
final GlobalKey<FormState> formKey = GlobalKey();
int? startTime;
int? endTime;
String? content;
int? selectedColorId;
@override
Widget build(BuildContext context) {
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
return SafeArea(
bottom: true,
child: GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
child: Container(
height: MediaQuery.of(context).size.height / 2 + bottomInset,
color: Colors.white,
child: Padding(
padding: EdgeInsets.only(bottom: bottomInset),
child: Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 16.0),
child: Form(
key: formKey,
autovalidateMode: AutovalidateMode.always,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_Time(
onStartSaved: (newValue) {
startTime = int.parse(newValue!);
},
onEndSaved: (newValue) {
endTime = int.parse(newValue!);
},
),
SizedBox(height: 16.0),
_Content(
onSaved: (newValue) {
content = newValue;
},
),
SizedBox(height: 16.0),
FutureBuilder<List<CategoryColor>>(
future: GetIt.I<LocalDatabase>().getCategoryColors(),
builder: (context, snapshot) {
print(snapshot.data);
if (snapshot.hasData &&
selectedColorId == null &&
snapshot.data!.isNotEmpty) {
selectedColorId = snapshot.data![0].id;
}
return _ColorPicker(
colors: snapshot.hasData ? snapshot.data! : [],
selectColorId: selectedColorId!,
);
}),
SizedBox(height: 16.0),
_SaveButton(
onPressed: onSavePressed,
),
],
),
),
),
),
),
),
);
}
void onSavePressed() {
if (formKey.currentState == null) {
return;
}
if (formKey.currentState!.validate()) {
formKey.currentState!.save();
} else {
print('에러가 있습니다.');
}
}
}
class _Time extends StatelessWidget {
final FormFieldSetter<String> onStartSaved;
final FormFieldSetter<String> onEndSaved;
const _Time(
{super.key, required this.onStartSaved, required this.onEndSaved});
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: CustomTextField(
label: '시작 시간',
isTime: true,
onSaved: onStartSaved,
)),
SizedBox(width: 16.0),
Expanded(
child: CustomTextField(
label: '마감 시간',
isTime: true,
onSaved: onEndSaved,
),
),
],
);
}
}
class _Content extends StatelessWidget {
final FormFieldSetter<String> onSaved;
const _Content({super.key, required this.onSaved});
@override
Widget build(BuildContext context) {
return Expanded(
child: CustomTextField(
label: '내용',
isTime: false,
onSaved: onSaved,
),
);
}
}
class _ColorPicker extends StatelessWidget {
final List<CategoryColor> colors;
final int selectColorId;
const _ColorPicker(
{super.key, required this.colors, required this.selectColorId});
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 8.0,
runSpacing: 10.0,
children: colors.map((e) => rendColor(e, selectColorId == e.id)).toList(),
);
}
Widget rendColor(CategoryColor color, bool isSelected) {
return Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(int.parse('FF${color.hexCode}', radix: 16)),
border:
isSelected ? Border.all(color: Colors.black, width: 1.0) : null,
),
height: 32,
width: 32);
}
}
class _SaveButton extends StatelessWidget {
final VoidCallback onPressed;
const _SaveButton({super.key, required this.onPressed});
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: PRIMARY_COLOR,
),
onPressed: onPressed,
child: Text('Save'),
),
);
}
}
drift_database.dart
import 'dart:io';
import 'package:calendar_schedule_exam/model/category_color.dart';
import 'package:calendar_schedule_exam/model/schedule.dart';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
part 'drift_database.g.dart';
@DriftDatabase(
tables: [
Schedules,
CategoryColors,
],
)
class LocalDatabase extends _$LocalDatabase {
LocalDatabase() : super(_openConnection());
// insert schedules
Future<int> createSchedule(SchedulesCompanion data) => into(schedules).insert(data);
// insert categoryColors
Future<int> createCategoryColor(CategoryColorsCompanion data) => into(categoryColors).insert(data);
// select all categoryColors
Future<List<CategoryColor>> getCategoryColors() => select(categoryColors).get();
@override
// TODO: implement schemaVersion
int get schemaVersion => 1;
}
LazyDatabase _openConnection() {
return LazyDatabase(() async {
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'db.sqlite'));
return NativeDatabase(file);
});
}오류내용
Launching lib/main.dart on iPhone 14 Pro Max in debug mode...
Running Xcode build...
Xcode build done. 7.8s
[VERBOSE-2:FlutterDarwinContextMetalImpeller.mm(35)] Using the Impeller rendering backend.
Debug service listening on ws://127.0.0.1:61505/HeTRp4ZQphA=/ws
Syncing files to device iPhone 14 Pro Max...
flutter: null
======== Exception caught by widgets library =======================================================
The following _TypeError was thrown building FutureBuilder<List<CategoryColor>>(dirty, state: _FutureBuilderState<List<CategoryColor>>#41541):
Null check operator used on a null value
The relevant error-causing widget was:
FutureBuilder<List<CategoryColor>> FutureBuilder:file:///Users/choiwooin/dev/flutterProject/calendar_schedule_exam/lib/component/schedule_bottom_sheet.dart:57:21
When the exception was thrown, this was the stack:
#0 _ScheduleBottomSheetState.build.<anonymous closure> (package:calendar_schedule_exam/component/schedule_bottom_sheet.dart:68:59)
#1 _FutureBuilderState.build (package:flutter/src/widgets/async.dart:612:55)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:5198:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5086:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#5 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#6 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#7 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5242:11)
답변 2
2
안녕하세요!
데이터 마이그레이션이 잘못 됐을 수 있습니다.
에뮬레이터/시뮬레이터에서 앱을 삭제한 후 다시 실행해보세요!
그래도 안되면 다시 질문 부탁드립니다.
감사합니다!
198강 (){onTap(e);}의 이해 돕기
0
26
1
video_call 플러그인 설치후 에러 발생
0
45
1
SDK 안드로이드 설치 질문!
0
60
1
코드팩토리 디스코드 링크 다시 부탁드려요~
0
92
1
Webview를 이용해서 URL 상의 페이지 출력 불가
0
70
1
홈스크린 함수를 함축해서 main.dart에 옮기는 문제
0
55
1
플레이스토어
0
59
1
아고라 엔진 init 함수의 반환타입이 Future<void> 이것의 의미는 무엇인가요?
0
55
1
가이드라인 질문
0
57
0
emulator 에러 환경설정 뭐가 문제 일까요??
0
76
1
emulator 실행 오류
0
93
3
Column을 가로방향 최대 사이즈를 차지하도록 하는 방법에 관련
0
71
1
pubspec.yaml에서 font를 추가하면서 weight 값을 지정하는 것이 의미가 있는 것인지 문의
0
43
1
setState()를 호출하지 않으면 build가 실행 안되는 건가요?
0
53
1
video_call 플러그인 설치시 에러문제
0
64
1
children 안의 if 문에서 { } 못쓰는 이유?
0
48
1
이렇게 오류가 떠요
0
63
1
AppBar 사용했는데
0
61
2
[문제해결] '오늘도 출첵!' 의 171번 강의에서 중요한 문제를 발견했습니다
0
56
1
StatefulWidget 실습 에러가 발생합니다.[해결완료]
0
63
1
Video Player 프로젝트에 대한 추가 질문
0
53
0
Row위젯이나 column위젯의 위치는 누가 정하나요??
0
42
1
geolocator 오류때문에 개발진행이 불가능입니다
0
63
1
API 관련 이슈
0
86
2





