iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0
AI Engineering

從行程到應援:30 天做出追星實用工具箱系列 第 3

Day 3:模組二/專輯與周邊收藏管理

  • 分享至 

  • xImage
  •  

一、前言

追星族的周邊與小卡數量種類眾多,需要輕量高效的本地資料庫進行分類與儲存。

技術介紹:
這次要用來存資料的工具叫做 Hive,可以把它想成是「一個很輕巧的筆記本」,專門用來幫 App 記住資料(例如你收藏了哪些專輯、周邊)。
它有幾個對一般開發者很友善的優點:

  • 手機、電腦、網頁都能用:不管是 iPhone、Android,還是桌面版、網頁版的 App,都可以直接使用同一套寫法,不用為了不同平台改來改去。
  • 速度快:因為資料是先放在記憶體裡處理,再用比較精簡的方式存起來,所以讀取、寫入都比傳統做法(SQL)快很多,App用起來比較不會卡。
  • 不用學資料庫語法:一般資料庫常常要寫複雜的SQL指令、還要規劃表格欄位,但 Hive 只要用put(存資料)跟 get(拿資料)這兩個簡單的動作就能完成,對新手非常友善。
  • 可以直接存「自己定義的資料格式」:假設你想存的是「專輯名稱+歌手+收藏日期」這種一整包的資料,Hive 也可以透過簡單的設定,直接把這種自訂格式存進去,不用拆成一堆零散的欄位。

二、今日任務

1. 安裝 Hive 相關套件

flutter pub add hive hive_flutter
flutter pub add --dev hive_generator build_runner

2. 設計周邊收藏 Data Model

import 'package:hive/hive.dart';

part 'item_model.g.dart';

@HiveType(typeId: 0)
class CollectionItem extends HiveObject {
  @HiveField(0)
  String name; // 項目名稱 (例如:IVE 1st Single 小卡)

  @HiveField(1)
  String category; // 分類 (專輯 / 小卡 / 周邊)

  @HiveField(2)
  DateTime dateAdded; // 收藏日期

  CollectionItem({
    required this.name,
    required this.category,
    required this.dateAdded,
  });
}

執行自動生成套件

flutter pub run build_runner build --delete-conflicting-outputs

3. 在 main.dart 初始化 Hive

開啟 lib/main.dart,在 main() 函式加入 Hive 初始化與 Adapter 註冊:

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'core/services/notification_service.dart';
import 'features/schedule/schedule_page.dart';
import 'features/live_translate/live_translate_page.dart';
import 'features/collection/models/item_model.dart';


final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

 
  await Hive.initFlutter();
  Hive.registerAdapter(CollectionItemAdapter());
  await Hive.openBox<CollectionItem>('collection_box'); // 開啟儲存盒

  // 初始化通知,並傳入點擊處置
  await NotificationService().init(onClick: (payload) {
    if (payload == 'open_translate') {
      // 點擊通知後,直接跳轉到即時翻譯頁面
      navigatorKey.currentState?.push(
        MaterialPageRoute(builder: (context) => const LiveTranslatePage()),
      );
    }
  });

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey, 
      title: '追星工具箱',
      theme: ThemeData(primarySwatch: Colors.pink, useMaterial3: true),
      home: const SchedulePage(),
    );
  }
}

4. 建立收藏管理介面

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'models/item_model.dart';

class CollectionPage extends StatefulWidget {
  const CollectionPage({super.key});

  @override
  State<CollectionPage> createState() => _CollectionPageState();
}

class _CollectionPageState extends State<CollectionPage> {
  final TextEditingController _nameController = TextEditingController();
  String _selectedCategory = '小卡';
  late Box<CollectionItem> _collectionBox;

  @override
  void initState() {
    super.initState();
    _collectionBox = Hive.box<CollectionItem>('collection_box');
  }

  void _addItem() {
    if (_nameController.text.isEmpty) return;
    final newItem = CollectionItem(
      name: _nameController.text,
      category: _selectedCategory,
      dateAdded: DateTime.now(),
    );
    _collectionBox.add(newItem); // 儲存進 Hive
    _nameController.clear();
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('周邊與小卡收藏庫')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _nameController,
                    decoration: const InputDecoration(
                      labelText: '收藏品名稱 (例如:應援棒 / 限量卡)',
                      border: OutlineInputBorder(),
                    ),
                  ),
                ),
                const SizedBox(width: 10),
                DropdownButton<String>(
                  value: _selectedCategory,
                  items: ['小卡', '專輯', '周邊'].map((String value) {
                    return DropdownMenuItem<String>(
                      value: value,
                      child: Text(value),
                    );
                  }).toList(),
                  onChanged: (val) => setState(() => _selectedCategory = val!),
                ),
              ],
            ),
            const SizedBox(height: 10),
            ElevatedButton.icon(
              icon: const Icon(Icons.add),
              label: const Text('新增至收藏庫'),
              onPressed: _addItem,
            ),
            const Divider(height: 30),
            Expanded(
              child: ValueListenableBuilder(
                valueListenable: _collectionBox.listenable(),
                builder: (context, Box<CollectionItem> box, _) {
                  if (box.values.isEmpty) {
                    return const Center(child: Text('目前還沒有收藏項目喔!'));
                  }
                  return ListView.builder(
                    itemCount: box.length,
                    itemBuilder: (context, index) {
                      final item = box.getAt(index);
                      return ListTile(
                        leading: Chip(label: Text(item?.category ?? '')),
                        title: Text(item?.name ?? ''),
                        subtitle: Text('${item?.dateAdded.toString().split(' ')[0]}'),
                        trailing: IconButton(
                          icon: const Icon(Icons.delete, color: Colors.red),
                          onPressed: () => item?.delete(), // 從 Hive 刪除
                        ),
                      );
                    },
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

檢查

  • [x] 執行 flutter pub run build_runner build
  • [x] 執行 App 後能順利新增收藏項目。
  • [x] 重啟 App,確認剛才輸入的收藏資料依然保留在畫面上

執行後,可看到右上角多了個書籤的標籤

螢幕擷取畫面 2026-09-09 150252

點進去就有收藏庫可自行新增物品

螢幕擷取畫面 2026-09-09 150316

右邊可以選擇周邊的種類,小卡、專輯、周邊,點選標籤後可在收藏品名稱輸入,完成後按下新增至收藏庫,下方就出現已新增的周邊

螢幕擷取畫面 2026-09-09 151437


上一篇
Day 2:模組一/追星行程追蹤與本地通知提醒功能實作Local Notification
下一篇
Day 4:模組三/追星花費紀錄與應援活動整理頁面
系列文
從行程到應援:30 天做出追星實用工具箱7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言