追星族的周邊與小卡數量種類眾多,需要輕量高效的本地資料庫進行分類與儲存。
技術介紹:
這次要用來存資料的工具叫做 Hive,可以把它想成是「一個很輕巧的筆記本」,專門用來幫 App 記住資料(例如你收藏了哪些專輯、周邊)。
它有幾個對一般開發者很友善的優點:
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 刪除
),
);
},
);
},
),
),
],
),
),
);
}
}
檢查
flutter pub run build_runner build
執行後,可看到右上角多了個書籤的標籤

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

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