iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0
Mobile Development

Flutter基礎入門系列 第 27

【Day 27】儲存時刻表的新資料

  • 分享至 

  • xImage
  •  

接續前一篇的文章【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();
  }
}

儲存新增的TimeBlock

這部份主要需要修改的僅有_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的檔案,並在其中新增了我們剛剛所建立的資料。
https://ithelp.ithome.com.tw/upload/images/20241011/20169446XYmwksHKkS.png


明天的內容將是在timetable顯示過去建立的資料,並讓使用者能夠對他們做修改並儲存更新的內容。謝謝閱讀到這裡的讀者,有任何問題或是想說的都歡迎留言與email!


上一篇
【Day 26】建立客製化的時刻表吧!
下一篇
【Day 28】時刻表的使用 - 續篇
系列文
Flutter基礎入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言