Isar状态无法持久化问题求助:需计数器APP示例解决方案
Isar持久化失效问题修复(计数器示例)
问题根源分析
你的代码存在两个核心问题导致重启后数据丢失:
- 每次启动强制覆盖数据:
initState中每次都会将初始值为9的CounterObject写入Isar,直接覆盖了之前存储的计数数据。 - ID匹配错误:
CounterObject使用Isar.autoIncrement作为ID,每次重启都会创建新的CounterObject实例(初始ID为0),读取时用这个新ID找不到之前存储的旧数据。
修复后的完整代码
1. main.dart
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isarapp/counter_schema.dart'; import 'package:isar/isar.dart'; import 'package:isarapp/home_screen.dart'; import 'package:path_provider/path_provider.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); final directory = await getApplicationDocumentsDirectory(); await Isar.open( [CounterObjectSchema], directory: directory.path, inspector: true, name: "isardb", ); runApp(const MyApp()); } class MyApp extends ConsumerWidget { const MyApp({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return ProviderScope( child: MaterialApp( debugShowCheckedModeBanner: false, title: 'Isar计数器示例', theme: ThemeData( primarySwatch: Colors.blue, ), home: const HomeScreen(), ), ); } }
2. counter_schema.dart
import 'package:isar/isar.dart'; part 'counter_schema.g.dart'; @collection class CounterObject { // 固定ID为1,确保始终操作同一条数据 Id id = 1; int counter; CounterObject({required this.counter}); }
3. home_screen.dart
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isar/isar.dart'; import 'package:isarapp/counter_schema.dart'; final counterProvider1 = StateProvider<int>((ref) { return 0; }); class HomeScreen extends ConsumerStatefulWidget { const HomeScreen({super.key}); @override ConsumerState<ConsumerStatefulWidget> createState() => _HomeScreenState(); } class _HomeScreenState extends ConsumerState<HomeScreen> { Isar? isar = Isar.getInstance("isardb"); late CounterObject counterObject; // 初始化计数器:优先读取本地存储,没有则设置初始值0 initCounter() async { final storedCounter = await isar?.collection<CounterObject>().get(1); if (storedCounter != null) { counterObject = storedCounter; ref.read(counterProvider1.notifier).state = storedCounter.counter; } else { // 首次启动,创建初始计数器 counterObject = CounterObject(counter: 0); await isar?.writeTxn( () async => await isar?.counterObjects.put(counterObject), ); ref.read(counterProvider1.notifier).state = 0; } } increment() async { counterObject.counter++; ref.read(counterProvider1.notifier).state = counterObject.counter; // 写入数据库 await isar?.writeTxn( () async => await isar?.counterObjects.put(counterObject), ); } @override void initState() { super.initState(); initCounter(); } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( ref.watch(counterProvider1).toString(), style: const TextStyle(fontSize: 54), ), const SizedBox(height: 30), GestureDetector( onTap: increment, child: Container( width: 200, height: 40, color: Colors.blue[300], child: const Center(child: Text("增加计数")), ), ), ], ), ), ), ); } }
关键修复点说明
- 固定数据ID:将
CounterObject的ID设为固定值1,确保每次操作的都是同一条计数数据,避免因autoIncrement导致的ID不匹配问题。 - 调整初始化逻辑:启动时先尝试读取本地存储的计数器,不存在时才创建初始值,避免每次启动覆盖已有数据。
- 移除冗余权限:使用
getApplicationDocumentsDirectory()获取的是应用私有目录,Android 10+无需额外存储权限,因此可以删除permission_handler相关代码。
内容的提问来源于stack exchange,提问作者AbdulHaseeeb
相关产品推荐
相关产品推荐

