I have basically used the same code in two different screens to get a list of Todos from the database. In the first screen I have just retrieved and displayed all the Todos. In the second screen I have displayed a list that contains a particular substring entered by the user in the search bar of the first screen.
The UI updates itself in the second (Searching_Items) Screen if I update a Todo item there but when I go back the first (Todo_List) screen, I have to hot reload to show that same change.
First Screen
class TodoListWidget extends StatefulWidget {
const TodoListWidget({Key? key}) : super(key: key);
@override
State<TodoListWidget> createState() => _TodoListWidgetState();
}
class _TodoListWidgetState extends State<TodoListWidget> {
var doneOrNot = null;
var iconChanger = Icons.check_box_outline_blank;
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Todo>>(
future: TodoServiceHelper().getTodos(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding:
EdgeInsets.only(left: 7, top: 19, right: 7, bottom: 7),
child: ListTile(
onTap: () async {
await showDialog(
barrierDismissible: false,
context: context,
builder: ((context) {
return EditTodoDialogue(
title: snapshot.data![index].title.toString(),
desc: snapshot.data![index].description.toString(),
id: snapshot.data![index].id.toString(),
isDone: snapshot.data![index].isDone,
);
}),
);
setState(() {});
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
dense: false,
visualDensity: VisualDensity(vertical: -3, horizontal: -3),
contentPadding:
EdgeInsets.only(left: 32, right: 32, top: 8, bottom: 8),
title: Text(
snapshot.data![index].title.toString(),
style: TextStyle(
decoration: doneOrNot,
color: Colors.black87,
fontSize: 30,
fontWeight: FontWeight.bold),
),
subtitle: Text(
snapshot.data![index].description.toString(),
style: TextStyle(
decoration: doneOrNot,
color: Colors.black45,
fontWeight: FontWeight.bold),
),
leading: IconButton(
color: Colors.blue,
icon: Icon(
!snapshot.data![index].isDone
? iconChanger
: Icons.check_box,
),
onPressed: () {
if (snapshot.data![index].isDone) {
Todo update = Todo(
title: snapshot.data![index].title.toString(),
description:
snapshot.data![index].description.toString(),
id: snapshot.data![index].id.toString(),
isDone: snapshot.data![index].isDone,
);
} else {}
}),
trailing: IconButton(
alignment: Alignment.center,
icon: Icon(
Icons.delete,
size: 30,
color: Color.fromARGB(198, 209, 40, 40),
),
onPressed: () {
setState(() {
TodoServiceHelper().deleteTodo(
snapshot.data![index].id.toString());
});
}),
),
);
},
);
} else if (snapshot.hasError) {
return Text("Oops!");
}
return Center(child: CircularProgressIndicator());
},
),
);
}
}
Second Screen
class ShowingSerachedTitle extends StatefulWidget {
String searchTerm;
ShowingSerachedTitle({required this.searchTerm});
@override
State<ShowingSerachedTitle> createState() => _ShowingSerachedTitleState();
}
class _ShowingSerachedTitleState extends State<ShowingSerachedTitle> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Todo>>(
future: TodoServiceHelper().searchTerm(widget.searchTerm),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(children: [
SizedBox(
height: 100,
),
Flexible(
child: Text(
'There are/isr ${snapshot.data!.length} with that search term',
style: TextStyle(fontSize: 50),
),
),
Flexible(
child: ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding:
EdgeInsets.only(left: 7, top: 19, right: 7, bottom: 7),
child: ListTile(
onTap: () async {
await showDialog(
barrierDismissible: false,
context: context,
builder: ((context) {
return EditTodoDialogue(
title: snapshot.data![index].title.toString(),
desc:
snapshot.data![index].description.toString(),
id: snapshot.data![index].id.toString(),
isDone: snapshot.data![index].isDone,
);
}),
);
setState(() {});
print('trying to update');
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
dense: false,
visualDensity:
VisualDensity(vertical: -3, horizontal: -3),
contentPadding: EdgeInsets.only(
left: 32, right: 32, top: 8, bottom: 8),
title: Text(
snapshot.data![index].title.toString(),
style: TextStyle(
color: Colors.black87,
fontSize: 30,
fontWeight: FontWeight.bold),
),
subtitle: Text(
snapshot.data![index].description.toString(),
style: TextStyle(
color: Colors.black45, fontWeight: FontWeight.bold),
),
trailing: IconButton(
alignment: Alignment.center,
icon: Icon(
Icons.delete,
size: 30,
color: Color.fromARGB(198, 209, 40, 40),
),
onPressed: () {
setState(() {
TodoServiceHelper().deleteTodo(
snapshot.data![index].id.toString());
print('trying to delete');
});
}),
),
);
},
))
]);
} else if (snapshot.hasError) {
return Text("Oops!");
}
return Center(child: CircularProgressIndicator());
},
),
);
}
}
I have used basically the same code in both the screens but the UI automatically updates in only the searching_Items screen
The functions used to update and delete Todo items:
Getting all the Todos
Future getItemCount() async {
final Database db = await initializeDB();
final List<Map<String, Object?>> queryResult = await db.query('todos');
var count = queryResult.length;
print(count);
return Future.value(count);
}
Updating Todos
Future<void> updateTodo(Todo todo) async {
final Database db = await initializeDB();
try {
await db
.update('todos', todo.toMap(), where: 'id= ?', whereArgs: [todo.id]);
} catch (e) {
print('$e');
}
}
Deleting Todos
Future<void> deleteTodo(String? idd) async {
final Database db = await initializeDB();
try {
await db.delete(
'todos',
where: 'id = ?',
whereArgs: [idd],
);
} catch (e) {
print('$e');
}
}
Filtering based on a substring provided by user
Future<List<Todo>> searchTerm(String term) async {
final Database db = await initializeDB();
final List<Map<String, Object?>> result = await db.query(
'todos',
columns: ['title', 'description', 'id'],
where: 'title || description LIKE ?',
whereArgs: ['%$term%'],
);
List<Todo> filtered = [];
for (var item in result) {
filtered.add(Todo.fromMap(item));
}
return filtered;
}
CodePudding user response:
When you go back the first (Todo_List) screen. You need to "setState(() {});" like this for exemple
ElevatedButton(
child: const Text('Second Page'),
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ShowingSerachedTitle()),
);
setState(() {});
},
),
I recommended you to use sqfentity