The ListView shows Item1, Item2 and Item3. When I try to delete Item2, the ListView incorrectly shows Item1 and Item2. The console shows the correct items in the list: Item1 and Item3.
HomeScreen:
class HomeScreen extends StatefulWidget {
@override
HomeScreenState createState() => new HomeScreenState();
}
class HomeScreenState extends State<HomeScreen> {
List<Todo> todos = new List();
@override
void initState() {
super.initState();
populateTodos();
}
void populateTodos() async {
TodoDatabase db = new TodoDatabase();
db.getAllTodos().then((newTodos) {
for (var todo in newTodos) {
print(todo.title + ", " + todo.id);
}
setState(() => todos = newTodos);
});
}
void openAddTodoScreen() async {
Navigator
.push(context,
new MaterialPageRoute(builder: (context) => new AddTodoScreen()))
.then((b) {
populateTodos();
});
}
void clearDb() async {
TodoDatabase db = new TodoDatabase();
db.clearDb();
populateTodos();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Todo App"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.delete),
onPressed: () => clearDb(),
),
new IconButton(
icon: new Icon(Icons.refresh),
onPressed: () => populateTodos(),
)
],
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: new ListView.builder(
padding: new EdgeInsets.all(10.0),
itemCount: todos.length,
itemBuilder: (BuildContext context, int index) {
return new TodoItem(todos[index], onDelete: (id) {
TodoDatabase db = new TodoDatabase();
print("ID: " + id);
db.deleteTodo(id).then((b) {
populateTodos();
});
});
},
),
)
],
),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.add), onPressed: () => openAddTodoScreen()),
);
}
}
DataBase Code:
class TodoDatabase {
TodoDatabase();
static Database _db;
Future<Database> get db async {
if (_db != null) {
return _db;
}
_db = await initDB();
return _db;
}
Future<Database> initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "main.db");
var theDb = await openDatabase(path, version: 1, onCreate: createDatabase);
return theDb;
}
void createDatabase(Database db, int version) async {
await db.execute("CREATE TABLE Todos(id STRING PRIMARY KEY, title TEXT, description TEXT)");
print("Database was Created!");
}
Future<List<Todo>> getAllTodos() async {
var dbClient = await db;
List<Map> res = await dbClient.query("Todos");
print(res);
return res.map((map) => new Todo(title: map["title"], description: map["description"], id: map["id"])).toList();
}
Future<Todo> getTodo(String id) async {
var dbClient = await db;
var res = await dbClient.query("Todos", where: "id = ?", whereArgs: [id]);
if (res.length == 0) return null;
return new Todo.fromDb(res[0]);
}
Future<int> addTodo(Todo todo) async {
var dbClient = await db;
int res = await dbClient.insert("Todos", todo.toMap());
return res;
}
Future<int> updateTodo(Todo todo) async {
var dbClient = await db;
int res = await dbClient.update(
"Todos",
todo.toMap(),
where: "id = ?",
whereArgs: [todo.id]);
return res;
}
Future<int> deleteTodo(String id) async {
var dbClient = await db;
var res = await dbClient.delete(
"Todos",
where: "id = ?",
whereArgs: [id]);
print("Deleted item");
return res;
}
Future<int> clearDb() async {
var dbClient = await db;
var res = await dbClient.execute("DELETE from Todos");
print("Deleted db contents");
return res;
}
}
This almost seems like a bug with Flutter. I have to add some more text because otherwise it won't let me post. I don't know how to illustrate the issue further. Thanks for your help!
I was missing a key. Here's the correct ListView.builder:
new ListView.builder(
key: new Key(randomString(20)),
padding: new EdgeInsets.all(10.0),
itemCount: todos.length,
itemBuilder: (BuildContext context, int index) {
return new TodoItem(todos[index], onDelete: (id) {
TodoDatabase db = new TodoDatabase();
db.deleteTodo(id).then((b) {
populateTodos();
});
});
},
),
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With