I am testing Hive NoSQL Database. I have succeeded in creating a database, putting a value, and getting a value.
However, I failed to delete the value. I've done a lot of searching, but I can't figure it out.
Also, when saving the value of TextFormField using Button, Get.Back(); was used using GetX, but it did not work. The value is saved, but the screen is not popped. So, I popped it using Navigation and it worked. I don't know what was the cause.
I'd appreciate it if you could tell me what the problem is.
home_screen.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hive_test1/component/todo_card.dart';
import 'package:hive_test1/db/database.dart';
import 'package:hive_test1/scr/form_screen.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
Get.to(() => FormScreen());
},
child: Icon(Icons.add),
),
appBar: AppBar(
centerTitle: true,
title: const Text('Hive Test'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ValueListenableBuilder(
valueListenable: Hive.box<Todos>('testTable').listenable(),
builder: (context, Box<Todos> box, child) {
return ListView.separated(
itemCount: box.length,
itemBuilder: (_, index) {
var item = box.get(index);
if (item == null) {
return Center(
child: Container(
child: Text('null'),
));
} else {
return TodoCard(
title: item.title,
note: item.note,
dateTime: item.dateTime,
id: item.id,
onPressed: () {
setState(() {
box.deleteAt(item.id); // This is not working.
});
});
}
},
separatorBuilder: (_, index) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 10),
child: Divider(),
);
},
);
}),
),
);
}
}
form_screen.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:hive_test1/db/database.dart';
class FormScreen extends StatefulWidget {
const FormScreen({Key? key}) : super(key: key);
@override
_FormScreenState createState() => _FormScreenState();
}
class _FormScreenState extends State<FormScreen> {
GlobalKey<FormState> formKey = GlobalKey();
String? title;
String? note;
DateTime? dateTime;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('Form Screen'),
),
body: Form(
key: formKey,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
renderTextFormField(
label: 'Title',
hintText: 'Please enter a title',
onSaved: (val) {
setState(() {
title = val;
});
},
validator: (val) {
if (val.length < 1) {
return 'Please enter a title';
}
return null;
}),
renderTextFormField(
label: 'Note',
hintText: 'Please enter a value',
onSaved: (val) {
setState(() {
note = val;
});
},
validator: (val) {
if (val.length < 1) {
return 'Please enter a note';
}
return null;
}),
saveButton(),
],
),
),
),
);
}
renderTextFormField({
required String label,
required onSaved,
required validator,
required hintText,
}) {
return Column(
children: [
Row(
children: [
Text(
label,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
const SizedBox(
height: 5,
),
TextFormField(
style: TextStyle(fontSize: 20),
autovalidateMode: AutovalidateMode.always,
onSaved: onSaved,
validator: validator,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
hintText: hintText,
border: const OutlineInputBorder(),
),
),
],
);
}
saveButton() {
return Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: () async {
var box = Hive.box<Todos>('testTable');
if (formKey.currentState!.validate()) {
formKey.currentState?.save();
int id = 0;
if (box.isNotEmpty) {
final prevItem = box.getAt(box.length - 1);
id = prevItem!.id 1;
}
box.put(
id,
Todos(
title: title!,
note: note!,
id: id,
dateTime: dateTime = DateTime.now(),
),
);
Get.snackbar(
'Saved!',
'Your form has been saved!',
);
print(title);
Navigator.of(context).pop(); // this is working
// Get.Back(); <- Not Working
} else if (formKey.currentState?.validate() == null) {
Get.snackbar(
"Required",
"All fields are required!",
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.white.withOpacity(0.5),
icon: Icon(
Icons.warning_amber_rounded,
color: Colors.red,
),
);
}
},
child: const Text(
'Save',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
),
],
);
}
}
database.dart
import 'package:hive/hive.dart';
part 'database.g.dart';
@HiveType(typeId: 1)
class Todos {
Todos(
{required this.title,
required this.note,
required this.id,
required this.dateTime});
@HiveField(0)
int id;
@HiveField(1)
String title;
@HiveField(2)
String note;
@HiveField(3)
DateTime dateTime;
}
CodePudding user response:
There was no answer to my #1 question, so I tried to find the answer myself. I haven't found an answer for the 2nd one yet.
Answer 1 should have declared VoidCallback instead of Function when declaring a Function.
Here's the code:
import 'package:flutter/material.dart';
class TodoCard extends StatefulWidget {
final String title;
final String note;
final int id;
final DateTime dateTime;
final VoidCallback onPressed;
// This is answer. VoidCallback instead of Function
renderIconButton() {
return IconButton(
onPressed: widget.onPressed, // This is answer.
icon: const Icon(
Icons.delete,
color: Colors.red,
size: 25,
),
);
}
return TodoCard(
title: item.title,
note: item.note,
dateTime: item.dateTime,
id: item.id,
onPressed: () => box.deleteAt(index),
);
CodePudding user response:
You are not deleting with
indexI guess. If that so, to delete withiduse.deleteinstead of.deleteAtmethod like:onPressed: () async { setState(() { await box.delete(item.id); }); }SnackBars anddialogs are considered asroutes in GetX. Therefore, you need to close that route usingGet.back()if they are open in order to navigate away from the containing screen/page:Get.back(); // to close the opened snackbar or dialog Get.back(); // to close the current page and go back
You need to use Get.back() twice essentially. But there's a problem with this. Calling Get.back() twice immediately closes your snackbar and never shown. You could use Future.delayed to overcome this:
await Future.delayed(Duration(seconds: 3), ()=> Get.back()); // allows the snackbar to be displayed for 3 seconds before closing
Get.back(); // Go back
