英文:
Flutter Isar stops working after hot restart
问题
我昨天开始学习Flutter Isar,我非常喜欢它。我用它创建了一个演示应用,但出现了一些问题。
这个应用有两个部分:原始(包含虚拟数据)和数据库(包含Isar数据库中的数据)。
当在原始部分中对项目进行标记为"starred"时,它会被添加到数据库中,并且图标会更改为"filled_star"。当在原始部分中取消对项目的标记时,期望它会从数据库部分中删除,并且图标会更改为"star_outline"。这一部分正常工作。
然而,当应用程序热重新启动时,我无法取消对项目的标记。请查看下面的GIF:
我尝试降级Isar的版本,但没有成功。
英文:
I started learning flutter isar yesterday and I couldn't love it more. I created a demo app with it and for some reason, it is not working as expected.
The app has two sections: Original(This contain the dummyData) and the Database(this contains data in the isar database).
When an item is starred in the original, it is added in the database and the icon is changed to filled_star. When the item is unstarred in the original section, it is expected to be removed from the database section and the icon is expected to change to star_outline. This is works fine.
However, when the app is hot-restarted, I am unable to unstar the items. Check the GIF below.
main.dart
import 'package:flutter/material.dart';
import 'package:isardemo/isar_files/course.dart';
import 'package:isardemo/isar_files/isar.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.blueGrey,
),
home: const MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final dummyData = [
Course()
..title = 'MTH 212'
..courseId = '1ab',
Course()
..title = 'STS 432'
..courseId = '2bc',
Course()
..title = 'SHS 555'
..courseId = '3de',
Course()
..title = 'HMM 999'
..courseId = '4fg',
Course()
..title = 'EEE 666'
..courseId = '5hi',
];
Future<void> onFavTap(IsarService courseData, Course course) async {
if (await courseData.isItemDuplicate(course)) {
await courseData.deleteCourse(course);
setState(() {});
debugPrint('${course.courseId} deleted');
} else {
await courseData.addCourse(course);
setState(() {});
debugPrint('${course.courseId} added');
}
}
final courseData = IsarService();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Isar'),
),
body: ListView(
padding: const EdgeInsets.all(20),
children: [
Center(
child: FutureBuilder(
initialData: courseData,
future: courseData.favoritesCount(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Text(
snapshot.data.toString(),
style:
const TextStyle(fontSize: 25, color: Colors.lightGreen),
);
} else {
return const LinearProgressIndicator();
}
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
courseData.cleanDb();
setState(() {});
},
child: const Text('Destroy Database')),
),
const Text('Original',
style: TextStyle(fontSize: 30, color: Colors.green)),
ListView.separated(
shrinkWrap: true,
separatorBuilder: (context, index) => const SizedBox(height: 5),
itemCount: dummyData.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
tileColor: Colors.blueGrey,
title: Text(dummyData[index].title),
trailing: IconButton(
icon: FutureBuilder(
// initialData: courseData.isItemDuplicate(dummyData[index]),
future: courseData.isItemDuplicate(dummyData[index]),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data) {
return const Icon(Icons.star);
} else {
return const Icon(Icons.star_border_outlined);
}
}
return const Icon(Icons.g_mobiledata,
color: Colors.green);
},
),
onPressed: () => onFavTap(courseData, dummyData[index])),
);
},
),
const SizedBox(height: 20),
const Text(
'database',
style: TextStyle(fontSize: 30, color: Colors.green),
),
FutureBuilder(
future: courseData.getAllCourses(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data![index].title),
trailing: InkWell(
onTap: () async {
await courseData
.deleteCourse(snapshot.data![index]);
setState(() {});
},
child: const Icon(Icons.star)),
);
},
);
} else {
return const Center(
child: LinearProgressIndicator(),
);
}
}),
],
),
);
}
}
course.dart
import 'package:isar/isar.dart';
part 'course.g.dart';
@Collection()
class Course {
Id id = Isar.autoIncrement;
late String courseId;
late String title;
late bool isFavorite = false; // new property
}
isar.dart
import 'package:path_provider/path_provider.dart';
import 'course.dart';
class IsarService {
late Future<Isar> _db;
IsarService() {
_db = openIsar();
}
Future<Isar> openIsar() async {
if (Isar.instanceNames.isEmpty) {
final directory = await getApplicationDocumentsDirectory();
return await Isar.open([CourseSchema],
inspector: true, directory: directory.path);
} else {
return await Future.value(Isar.getInstance());
}
}
Future<void> addCourse(Course course) async {
final isar = await _db;
await isar.writeTxn(() async {
await isar.courses.put(course);
});
}
Future<bool> isItemDuplicate(Course course) async {
final isar = await _db;
final count =
await isar.courses.filter().courseIdContains(course.courseId).count();
return count > 0;
}
Future<List<Course>> getAllCourses() async {
final isar = await _db;
return isar.courses.where().findAll();
}
Future<void> deleteCourse(Course course) async {
final isar = await _db;
await isar.writeTxn(() async {
await isar.courses.delete(course.id);
});
}
Future<String> favoritesCount() async {
final isar = await _db;
final count = await isar.courses.count();
return count.toString();
}
Future<void> cleanDb() async {
final isar = await _db;
await isar.writeTxn(() => isar.clear());
}
}
I tried downgrading the isar version but it didn't work.
答案1
得分: 0
我修复了它!我改用了Course的id而不是自动递增的id。但是Id期望一个整数,所以我不得不使用fastHash
将Course的id转换为整数。
course.dart
@Collection()
class Course {
late String id;
Id get courseId => fastHash(id);
late String title;
}
int fastHash(String string) {
var hash = 0xcbf29ce484222325;
var i = 0;
while (i < string.length) {
final codeUnit = string.codeUnitAt(i++);
hash ^= codeUnit >> 8;
hash *= 0x100000001b3;
hash ^= codeUnit & 0xFF;
hash *= 0x100000001b3;
}
return hash;
}
英文:
I fixed it! Instead of auto-incrementing the id, I used the Course's id instead. But Id expects an integer so I had to convert the Course's id into an integer using the fastHash
.
course.dart
<!-- language: lang-js -->
@Collection()
class Course {
late String id;
Id get courseId => fastHash(id);
late String title;
}
int fastHash(String string) {
var hash = 0xcbf29ce484222325;
var i = 0;
while (i < string.length) {
final codeUnit = string.codeUnitAt(i++);
hash ^= codeUnit >> 8;
hash *= 0x100000001b3;
hash ^= codeUnit & 0xFF;
hash *= 0x100000001b3;
}
return hash;
}
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论