一、前言
业务需求要使用到TodoList的功能,查找到类似的方案,但存在一定的缺陷,为了实现想要的功能,决定自己动手来实现,以下技术实现难度不大,就是有坑,接下来是填坑过程。
二、效果图
三、TodoList逻辑
- TodoList的标题效果(CheckboxListTile)
- 左右滑动删除(Dismissible)
- 数据持久化处理(sqlite)
四、具体实现方案
- 使用的第三方库
sqflite: ^1.1.6+5
- 主要代码
///数据库处理
///查询数据库
Future _getPersonProvider(Database db) async {
List<Map<String, dynamic>> maps =
await db.rawQuery("select * from $name ");
return maps;
}
///插入到数据库
Future insert(TodoModel model) async {
Database db = await getDataBase();
var userProvider = await _getPersonProvider(db);
if(model.id!=null){
if (userProvider != null) {
///删除数据
await db.delete(name, where: "$columnId = ?", whereArgs: [model.id]);
}
}
await db.rawInsert("insert into $name ($columnTitle,$columnIsDone) values (?,?)",[model.title,model.isDone]);
List<Map<String, dynamic>> maps =
await db.rawQuery("SELECT LAST_INSERT_ROWID();", null);
if (maps.length > 0) {
TodoModel userModel = await TodoModel.fromJson(maps[0]);
return userModel.lastid;
}
return null;
}
///更新数据库
Future<void> update(TodoModel model) async {
Database database = await getDataBase();
await database.rawUpdate(
"update $name set $columnTitle = ?,$columnIsDone = ? where $columnId= ?",[model.title,model.isDone,model.id]);
}
///删除数据
Future<void> delete(TodoModel model) async {
Database database = await getDataBase();
await database.delete(name, where: "$columnId = ?", whereArgs: [model.id]);
}
// 主要界面代码
Widget _createListView(todos, onTodoToggle) {
return ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return Dismissible(
background: Container(
color: Colors.green,
// 这里使用 ListTile 因为可以快速设置左右两端的Icon
child: ListTile(
leading: Icon(
Icons.delete,
color: Colors.white,
),
),
),
secondaryBackground: Container(
color: Colors.red,
// 这里使用 ListTile 因为可以快速设置左右两端的Icon
child: ListTile(
trailing: Icon(
Icons.delete,
color: Colors.white,
),
),
),
// Key
key: Key(UniqueKey().toString()),
// Child
child: CheckboxListTile(
value: todos[index].isDone,
activeColor: Colors.red,
title: todos[index].isDone
? Text(
todos[index].title,
style: TextStyle(
color: Colors.grey,
decoration: TextDecoration.lineThrough,
decorationColor: Colors.grey,
),
)
: Text(todos[index].title),
controlAffinity: ListTileControlAffinity.leading,
onChanged: (bool isChecked) {
onTodoToggle(todos[index], isChecked);
},
),
onDismissed: (direction) {
// 展示 SnackBar
// Scaffold.of(context).showSnackBar(SnackBar(
// content: Text('删除了${todos[index].title}'),
// ));
// 删除后刷新列表,以达到真正的删除
delete(todos[index].id);
setState(() {
todos.removeAt(index);
});
},
confirmDismiss: (direction) async {
var _confirmContent;
var _alertDialog;
// 从右向左 也就是删除
_confirmContent = '确认删除:${todos[index].title}?';
_alertDialog = AlertDialog(
title: Text(_confirmContent),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop(true);
},
child: Text('确认'),
),
FlatButton(
onPressed: () {
Navigator.of(context).pop(false);
},
child: Text('取消'),
)
],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20))),
);
// else if (direction == DismissDirection.startToEnd) {
// _confirmContent = '确认收藏${_listData[index]}?';
// _alertDialog = _createDialog(
// _confirmContent,
// () {
// // 展示 SnackBar
// Scaffold.of(context).showSnackBar(SnackBar(
// content: Text('确认收藏${_listData[index]}'),
// duration: Duration(milliseconds: 400),
// ));
// Navigator.of(context).pop(true);
// },
// () {
// // 展示 SnackBar
// Scaffold.of(context).showSnackBar(SnackBar(
// content: Text('不收藏${_listData[index]}'),
// duration: Duration(milliseconds: 400),
// ));
// Navigator.of(context).pop(false);
// },
// );
// }
var isDismiss = await showDialog(
context: context,
builder: (BuildContext context) {
return _alertDialog;
});
return isDismiss;
},
);
},
);
}
五、注意事项
- sqlite数据库的查看方式,Android studio
在android项目的build.gradle中添加代码
debugImplementation 'com.amitshekhar.android:debug-db:1.0.6'
之后Sync,启动AVD或者连接USB设备
在Logcat中输入D/DebugDB,即可查看IP与端口,在浏览器中打开访问即可
之后再用浏览器访问
localhost:8080
即可查看数据库中的结构及各表的内容
数据加载完成后无效果,需要点击按钮才有
通过加载进度条组件来实现效果,当sqlite的数据全部获取完进度条结束,显示页面。sqlite添加完成后返回id,配合更新删除
await db.rawInsert("insert into $name ($columnTitle,$columnIsDone) values (?,?)",[model.title,model.isDone]);
List<Map<String, dynamic>> maps =
await db.rawQuery("SELECT LAST_INSERT_ROWID();", null);
if (maps.length > 0) {
TodoModel userModel = await TodoModel.fromJson(maps[0]);
return userModel.lastid;
插入完成后通过
await db.rawQuery("SELECT LAST_INSERT_ROWID();", null);
返回{ LAST_INSERT_ROWID(),1}
最后附上Demo地址,如有什么不足和错误请指正,觉得受用反手就给颗吧