Flutter中如何通过ID获取特定数据并在ListView展示
需求:通过ID获取特定数据并在ListView展示
我已经在Flutter项目中用sqflite实现了数据的查看、插入、删除及更新操作,现在需要实现通过ID获取特定数据并在ListView中展示,以下是我的现有代码:
main.dart 文件
class _SqliteAppState extends State<SqliteApp> { int? selectedId; final textController = TextEditingController(); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: TextField( controller: textController, ), ), body: Center( child: FutureBuilder<List<Grocery>>( future: DatabaseHelper.instance.getGroceries(), builder: (BuildContext context, AsyncSnapshot<List<Grocery>> snapshot) { if (!snapshot.hasData) { return Center(child: Text('Loading...')); } return snapshot.data!.isEmpty ? Center(child: Text('No Groceries in List.')) : ListView( children: snapshot.data!.map((grocery) { return Center( child: Card( color: selectedId == grocery.id ? Colors.white70 : Colors.white, child: ListTile( title: Text(grocery.name), onTap: () { setState(() { if (selectedId == null) { textController.text = grocery.name; selectedId = grocery.id; } else { textController.text = ''; selectedId = null; } }); }, onLongPress: () { setState(() { DatabaseHelper.instance.remove(grocery.id!); }); }, ), ), ); }).toList(), ); }), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.save), onPressed: () async { selectedId != null ? await DatabaseHelper.instance.update( Grocery(id: selectedId, name: textController.text), ) : await DatabaseHelper.instance.add( Grocery(name: textController.text), ); setState(() { textController.clear(); selectedId = null; }); }, ), ), ); } }
模型类代码
class Grocery { int? id; String name; Grocery({this.id, required this.name}); factory Grocery.fromMap(Map<String, dynamic> json) => Grocery( id: json['id'], name: json['name'], ); Map<String, dynamic> toMap() { return { 'id': id, 'name': name, }; } }
DatabaseHelper类代码
class DatabaseHelper { DatabaseHelper._privateConstructor(); static final DatabaseHelper instance = DatabaseHelper._privateConstructor(); static Database? _database; Future<Database> get database async => _database ??= await _initDatabase(); Future<Database> _initDatabase() async { Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, 'groceries.db'); return await openDatabase( path, version: 1, onCreate: _onCreate, ); } Future _onCreate(Database db, int version) async { await db.execute(''' CREATE TABLE groceries( id INTEGER PRIMARY KEY, name TEXT ) '''); } Future<List<Grocery>> getGroceries() async { Database db = await instance.database; var groceries = await db.query('groceries', orderBy: 'name'); List<Grocery> groceryList = groceries.isNotEmpty ? groceries.map((c) => Grocery.fromMap(c)).toList() : []; return groceryList; } Future<int> add(Grocery grocery) async { Database db = await instance.database; return await db.insert('groceries', grocery.toMap()); } Future<int> remove(int id) async { Database db = await instance.database; return await db.delete('groceries', where: 'id = ?', whereArgs: [id]); } Future<int> update(Grocery grocery) async { Database db = await instance.database; return await db.update('groceries', grocery.toMap(), where: "id = ?", whereArgs: [grocery.id]); } }
实现方案
1. 在DatabaseHelper中添加通过ID查询单条数据的方法
在DatabaseHelper类里新增方法,用于根据ID获取指定的Grocery数据:
Future<Grocery?> getGroceryById(int id) async { Database db = await instance.database; var result = await db.query('groceries', where: 'id = ?', whereArgs: [id]); return result.isNotEmpty ? Grocery.fromMap(result.first) : null; }
2. 修改页面逻辑实现数据展示
以下示例实现两种查询展示方式:点击列表项自动查询展示单条数据,或手动输入ID查询展示。
修改_SqliteAppState代码:
class _SqliteAppState extends State<SqliteApp> { int? selectedId; Grocery? selectedGrocery; // 存储选中的单条数据 final textController = TextEditingController(); final idQueryController = TextEditingController(); // 手动输入ID的控制器 // 根据ID获取数据的方法 Future<void> fetchGroceryById(int id) async { Grocery? grocery = await DatabaseHelper.instance.getGroceryById(id); setState(() { selectedGrocery = grocery; }); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Row( children: [ Expanded( child: TextField( controller: textController, decoration: const InputDecoration(hintText: '输入商品名称'), ), ), const SizedBox(width: 10), Expanded( child: TextField( controller: idQueryController, decoration: const InputDecoration(hintText: '输入ID查询'), keyboardType: TextInputType.number, ), ), ElevatedButton( onPressed: () { if (idQueryController.text.isNotEmpty) { fetchGroceryById(int.parse(idQueryController.text)); } }, child: const Text('查询'), ) ], ), ), body: Column( children: [ // 展示通过ID查询到的单条数据 if (selectedGrocery != null) Card( margin: const EdgeInsets.all(16), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('ID: ${selectedGrocery!.id}'), const SizedBox(height: 8), Text('商品名称: ${selectedGrocery!.name}'), ], ), ), ), // 原有商品列表 Expanded( child: FutureBuilder<List<Grocery>>( future: DatabaseHelper.instance.getGroceries(), builder: (BuildContext context, AsyncSnapshot<List<Grocery>> snapshot) { if (!snapshot.hasData) { return const Center(child: Text('加载中...')); } return snapshot.data!.isEmpty ? const Center(child: Text('列表为空')) : ListView( children: snapshot.data!.map((grocery) { return Center( child: Card( color: selectedId == grocery.id ? Colors.white70 : Colors.white, child: ListTile( title: Text(grocery.name), onTap: () { setState(() { textController.text = grocery.name; selectedId = grocery.id; // 点击列表项时自动查询该ID的数据 fetchGroceryById(grocery.id!); }); }, onLongPress: () { setState(() { DatabaseHelper.instance.remove(grocery.id!); }); }, ), ), ); }).toList(), ); }), ), ], ), floatingActionButton: FloatingActionButton( child: const Icon(Icons.save), onPressed: () async { selectedId != null ? await DatabaseHelper.instance.update( Grocery(id: selectedId, name: textController.text), ) : await DatabaseHelper.instance.add( Grocery(name: textController.text), ); setState(() { textController.clear(); selectedId = null; selectedGrocery = null; // 清空选中数据 }); }, ), ), ); } }
3. 逻辑说明
getGroceryById方法通过db.query指定where条件查询单条数据,无匹配时返回null。- 页面新增了手动输入ID查询的功能,同时保留点击列表项自动查询展示的逻辑。
- 查询到的单条数据会在列表上方以卡片形式展示,直观呈现对应ID的商品信息。
内容的提问来源于stack exchange,提问作者sameera
相关产品推荐
相关产品推荐

