接續前一篇的文章【Day 26】建立客製化的時刻表吧!,今天筆者將繼續在時刻表上做修改。本篇中,將著重於資料存取的部份,並且修改Block類別並建立新的子類別。
在寫的過程中,筆者發現若將blocks.dart中的子類別都放至於同一檔案child_blocks.dart裡,會使得程式碼偏長,不太易閱讀,因此決定將其拆成兩個檔案:time_blocks.dart與todo_blocks.dart。前者用於存放Timetable頁面的檔案,後者用於存取Todo頁面的資料(嗯對,我決定將原本的TimeBlock與TimeBlocksDb重新命名為TodoBlock與TodoBlocksDb)。
現在的資料夾結構如下:
lib/
├── data/
│ ├── data/
│ │ └── timeblocks.db
│ └── models/
│ ├── blocks.dart
│ ├── time_blocks.dart (for TimetablePage)
│ └── todo_blocks.dart (for TodoPage)
├── main.dart
└── presentation/
├── pages/
│ ├── schedule.dart
│ ├── settings.dart
│ ├── timetable.dart
│ └── todo.dart
├── presentation.dart
└── widgets/
└── todo_entry_form.dart
而todo_blocks.dart的內容與之前相差無幾,故不特別提及。至於time_blocks.dart的類別與todo的主要差異為timeblock將estimatedTime, deadline的property給改為startTime, endTime,用於存取事件發生的起始及結束時間。
import 'package:schedrag/data/models/blocks.dart';
class TimeBlock extends Block {
late DateTime startTime, endTime;
TimeBlock()
: startTime = DateTime.now(),
endTime = DateTime.now();
TimeBlock.name(super.name)
: startTime = DateTime.now(),
endTime = DateTime.now(),
super.name();
TimeBlock.detail(
{super.name,
super.category,
super.notes,
DateTime? startTime,
DateTime? endTime})
: super.detail() {
if (startTime == null) {
this.startTime = DateTime.now();
} else {
this.startTime = startTime;
}
if (endTime == null) {
this.endTime = DateTime.now();
} else {
this.endTime = endTime;
}
}
@override
Map<String, Object?> toMap() {
return {
'id': id,
'name': name,
'category': category,
'startTime': startTime.toString(),
'endTime': endTime.toString(),
'notes': notes,
};
}
DateTime setTime(
{int month = 0, int day = 0, int hour = 0, int minute = 0}) =>
DateTime(2000, month, day, hour, minute);
@override
TimeBlock toBlock(Map<String, Object?> data) {
return TimeBlock.detail(
name: data['name'].toString(),
category: data['category'].toString(),
startTime: DateTime.tryParse(data['startTime'].toString()),
endTime: DateTime.tryParse(data['endTime'].toString()),
notes: data['notes'].toString(),
);
}
}
class TimeBlocksDb extends BlocksDb {
static const String _executeSQL = '''
id INTEGER PRIMARY KEY,
name TEXT, category TEXT,
startTime DATETIME,
endTime DATETIME,
notes TEXT''';
TimeBlocksDb()
: super(
dbFilename: 'TimeBlock.db',
tableName: 'Timetable',
executeSQL: _executeSQL);
Future<List<TimeBlock>?> getAll() async {
if (!dbIsOpen) open();
List<Map<String, Object?>>? table =
await db?.rawQuery('SELECT * FROM $tableName');
notifyListeners();
return table?.map((data) => TimeBlock().toBlock(data)).toList();
}
}
這部份主要需要修改的僅有_TimetablePageState
中的_onCreateEvent
,也就是使用者藉由拖拉建立新物件時,加入一個TimeBlocksDB().insert
即可。
CalendarEvent<TimeBlock> _onCreateEvent(DateTimeRange dateTimeRange) {
TimeBlock newBlock = TimeBlock.detail(
name: 'new event',
category: null,
notes: null,
startTime: dateTimeRange.start,
endTime: dateTimeRange.end);
db?.insert(newBlock);
return CalendarEvent(
dateTimeRange: dateTimeRange,
eventData: newBlock,
);
}
而db
則是在_TimetablePageState
物件建構時便設定好數值,也就是在initState()
函式中設定。
TimeBlocksDb? db;
@override
void initState() {
super.initState();
db = TimeBlocksDb();
此時於應用程式中建立新的方塊時,可以看到程式已經建立一個TimeBlock.db的檔案,並在其中新增了我們剛剛所建立的資料。
明天的內容將是在timetable顯示過去建立的資料,並讓使用者能夠對他們做修改並儲存更新的內容。謝謝閱讀到這裡的讀者,有任何問題或是想說的都歡迎留言與email!
- email: nnyjan02426@gmail.com
- github
- Schedrag