Flutter 的 sqflite 查询
Flutter's sqflite queries
我正在使用一个已经存在的数据库 dictionary.db
,它有一个 table words
并且有 4 列 id
、englishWord
、germanWord
, isFavorite
.
我正在尝试使用 Sqflite return 一个基于英语输入的德语单词列表,用户流程几乎是这样工作的:用户输入一个英语单词(示例:"Ability")和我 return 该词的德语同义词列表。
我的问题是我不知道如何使用我正在尝试的方法return获取完整列表,而不仅仅是预期的搜索结果
这是我的实体:
class Word {
final String id;
final String eng;
final String ger;
final String isFav;
Word({this.id, this.eng, this.ger, this.isFav});
Map<String, dynamic> toMap() {
return {
'wordId': id,
'englishWord': eng,
'germanWord': ger,
'isFavorite': isFav,
};
}
factory Word.fromMap(Map<String, dynamic> json) => new Word(
id: json['wordId'],
eng: json['englishWord'],
ger: json['germanWord'],
isFav: json['isFavorite']
);
}
这是我的数据库助手class:
class DatabaseHelper{
DatabaseHelper._();
static final DatabaseHelper databaseHelper = DatabaseHelper._();
Database _database;
static const String DB_NAME = "dict.db";
static const String TABLE = "words";
static const String ID = "wordId";
static const String ENGLISH_WORD = "englishWord";
static const String GERMAN_WORD = "germanWord";
static const String IS_FAV = "isFavorite";
Future<Database> get database async {
if (_database != null) return _database;
_database = await getDatabaseInstance();
return _database;
}
Future<Database> getDatabaseInstance() async {
io.Directory directory = await getApplicationDocumentsDirectory();
String path = join(directory.path, DB_NAME);
return await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
"$ID TEXT,"
"$ENGLISH_WORD TEXT,"
"$GERMAN_WORD TEXT,"
"$IS_FAV TEXT"
")");
});
}
//This is where I get the search result list
//I am stuck here I don't know where to go from here, I only get the full list
Future<List<Word>> searchEnglishResults(String userSearch) async{
final db = await database;
var response = await db.query("Word");
List<Word> list = response.map((c) => Word.fromMap(c)).toList();
return list;
}
我假设数据库如下所示:
|id | englidhWord | germanWord | isFavorite |
|-------|-------------|-------------------|------------|
| 'id0' | 'bye' | 'Tschüss' | 'false' |
| 'id1' | 'bye' | 'Auf Wiedersehen' | 'true' |
所以如果用户搜索 "bye",she/he 应该会收到 ['Tschüss','Auf Wiedersehen'](Word 模型不仅是德语单词)。
为此,query
有一些选项,例如 where
和 whereArgs
,您可以使用它们来搜索数据库中的特定行。
此处我们要在数据库中搜索其 englidhWord
字段值为 bye
的行。
这是您的数据库的编辑版本:
import 'dart:io';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sudoku/src/word.dart';
class DatabaseHelper {
DatabaseHelper._();
static final DatabaseHelper databaseHelper = DatabaseHelper._();
Database _database;
String DB_NAME = "dict.db";
static const String TABLE = "words";
static const String ID = "wordId";
static const String ENGLISH_WORD = "englishWord";
static const String GERMAN_WORD = "germanWord";
static const String IS_FAV = "isFavorite";
Future<Database> get database async {
if (_database != null) return _database;
_database = await getDatabaseInstance();
return _database;
}
Future<Database> getDatabaseInstance() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = join(directory.path, DB_NAME);
return await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
"$ID TEXT,"
"$ENGLISH_WORD TEXT,"
"$GERMAN_WORD TEXT,"
"$IS_FAV TEXT"
")");
});
}
//add new words
Future<int> add(Word word) async {
final db = await database;
var response = await db.insert(TABLE, word.toMap());
return response;
}
//This is where I get the search result list
//I am stuck here I don't know where to go from here, I only get the full list
Future<List<Word>> searchEnglishResults(String userSearch) async {
final db = await database;
var response = await db
.query(TABLE, where: '$ENGLISH_WORD = ?', whereArgs: [userSearch]);
List<Word> list = response.map((c) => Word.fromMap(c)).toList();
return list;
}
}
然后我在名为 MyApp
的页面上使用列表视图显示结果
import 'package:flutter/material.dart';
import 'package:sudoku/src/db.dart';
import 'package:sudoku/src/word.dart';
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
DatabaseHelper db;
@override
void initState() {
db = DatabaseHelper.databaseHelper;
add();
super.initState();
}
add() async {
// await db.add(Word(eng: 'hi', ger: 'Hallo', id: 'id2', isFav: 'true'));
// await db.add(Word(eng: 'bye', ger: 'Tschüss', id: 'id0', isFav: 'fasle'));
// await db.add(
// Word(eng: 'bye', ger: 'Auf Wiedersehen', id: 'id0', isFav: 'true'));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: FutureBuilder<List<Word>>(
future: db.searchEnglishResults('bye'),
builder: (BuildContext context, AsyncSnapshot<List<Word>> snapshot) {
if (snapshot.hasData)
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].ger),
subtitle: Text(snapshot.data[index].eng),
trailing: Text(snapshot.data[index].isFav),
);
},
itemCount: snapshot.data.length,
);
return Center(
child: CircularProgressIndicator(),
);
},
),
);
}
}
我在数据库和 MyApp 的 initState 中包含了一个名为 "add" 的函数,用于向数据库添加新词。
如果你多次刷新应用程序,它会添加重复的行,原因是你应该使数据库字段之一唯一,这里可以id
这样做你应该创建table 如下所示:
return await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
"$ID TEXT NOT NULL PRIMARY KEY,"
"$ENGLISH_WORD TEXT,"
"$GERMAN_WORD TEXT,"
"$IS_FAV TEXT"
")");
});
还有DB中的add
函数,你应该选择当它面对一个重复的行(这里是Word)时应该做什么,有一些选项,一个可以是替换它,它应该改变像这样:
//add new words
Future<int> add(Word word) async {
final db = await database;
var response = await db.insert(TABLE, word.toMap(), conflictAlgorithm: ConflictAlgorithm.replace);
return response;
}
我希望这就是您要找的东西。
我正在使用一个已经存在的数据库 dictionary.db
,它有一个 table words
并且有 4 列 id
、englishWord
、germanWord
, isFavorite
.
我正在尝试使用 Sqflite return 一个基于英语输入的德语单词列表,用户流程几乎是这样工作的:用户输入一个英语单词(示例:"Ability")和我 return 该词的德语同义词列表。
我的问题是我不知道如何使用我正在尝试的方法return获取完整列表,而不仅仅是预期的搜索结果
这是我的实体:
class Word {
final String id;
final String eng;
final String ger;
final String isFav;
Word({this.id, this.eng, this.ger, this.isFav});
Map<String, dynamic> toMap() {
return {
'wordId': id,
'englishWord': eng,
'germanWord': ger,
'isFavorite': isFav,
};
}
factory Word.fromMap(Map<String, dynamic> json) => new Word(
id: json['wordId'],
eng: json['englishWord'],
ger: json['germanWord'],
isFav: json['isFavorite']
);
}
这是我的数据库助手class:
class DatabaseHelper{
DatabaseHelper._();
static final DatabaseHelper databaseHelper = DatabaseHelper._();
Database _database;
static const String DB_NAME = "dict.db";
static const String TABLE = "words";
static const String ID = "wordId";
static const String ENGLISH_WORD = "englishWord";
static const String GERMAN_WORD = "germanWord";
static const String IS_FAV = "isFavorite";
Future<Database> get database async {
if (_database != null) return _database;
_database = await getDatabaseInstance();
return _database;
}
Future<Database> getDatabaseInstance() async {
io.Directory directory = await getApplicationDocumentsDirectory();
String path = join(directory.path, DB_NAME);
return await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
"$ID TEXT,"
"$ENGLISH_WORD TEXT,"
"$GERMAN_WORD TEXT,"
"$IS_FAV TEXT"
")");
});
}
//This is where I get the search result list
//I am stuck here I don't know where to go from here, I only get the full list
Future<List<Word>> searchEnglishResults(String userSearch) async{
final db = await database;
var response = await db.query("Word");
List<Word> list = response.map((c) => Word.fromMap(c)).toList();
return list;
}
我假设数据库如下所示:
|id | englidhWord | germanWord | isFavorite |
|-------|-------------|-------------------|------------|
| 'id0' | 'bye' | 'Tschüss' | 'false' |
| 'id1' | 'bye' | 'Auf Wiedersehen' | 'true' |
所以如果用户搜索 "bye",she/he 应该会收到 ['Tschüss','Auf Wiedersehen'](Word 模型不仅是德语单词)。
为此,query
有一些选项,例如 where
和 whereArgs
,您可以使用它们来搜索数据库中的特定行。
此处我们要在数据库中搜索其 englidhWord
字段值为 bye
的行。
这是您的数据库的编辑版本:
import 'dart:io';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sudoku/src/word.dart';
class DatabaseHelper {
DatabaseHelper._();
static final DatabaseHelper databaseHelper = DatabaseHelper._();
Database _database;
String DB_NAME = "dict.db";
static const String TABLE = "words";
static const String ID = "wordId";
static const String ENGLISH_WORD = "englishWord";
static const String GERMAN_WORD = "germanWord";
static const String IS_FAV = "isFavorite";
Future<Database> get database async {
if (_database != null) return _database;
_database = await getDatabaseInstance();
return _database;
}
Future<Database> getDatabaseInstance() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = join(directory.path, DB_NAME);
return await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
"$ID TEXT,"
"$ENGLISH_WORD TEXT,"
"$GERMAN_WORD TEXT,"
"$IS_FAV TEXT"
")");
});
}
//add new words
Future<int> add(Word word) async {
final db = await database;
var response = await db.insert(TABLE, word.toMap());
return response;
}
//This is where I get the search result list
//I am stuck here I don't know where to go from here, I only get the full list
Future<List<Word>> searchEnglishResults(String userSearch) async {
final db = await database;
var response = await db
.query(TABLE, where: '$ENGLISH_WORD = ?', whereArgs: [userSearch]);
List<Word> list = response.map((c) => Word.fromMap(c)).toList();
return list;
}
}
然后我在名为 MyApp
import 'package:flutter/material.dart';
import 'package:sudoku/src/db.dart';
import 'package:sudoku/src/word.dart';
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
DatabaseHelper db;
@override
void initState() {
db = DatabaseHelper.databaseHelper;
add();
super.initState();
}
add() async {
// await db.add(Word(eng: 'hi', ger: 'Hallo', id: 'id2', isFav: 'true'));
// await db.add(Word(eng: 'bye', ger: 'Tschüss', id: 'id0', isFav: 'fasle'));
// await db.add(
// Word(eng: 'bye', ger: 'Auf Wiedersehen', id: 'id0', isFav: 'true'));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: FutureBuilder<List<Word>>(
future: db.searchEnglishResults('bye'),
builder: (BuildContext context, AsyncSnapshot<List<Word>> snapshot) {
if (snapshot.hasData)
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].ger),
subtitle: Text(snapshot.data[index].eng),
trailing: Text(snapshot.data[index].isFav),
);
},
itemCount: snapshot.data.length,
);
return Center(
child: CircularProgressIndicator(),
);
},
),
);
}
}
我在数据库和 MyApp 的 initState 中包含了一个名为 "add" 的函数,用于向数据库添加新词。
如果你多次刷新应用程序,它会添加重复的行,原因是你应该使数据库字段之一唯一,这里可以id
这样做你应该创建table 如下所示:
return await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE IF NOT EXISTS $TABLE ("
"$ID TEXT NOT NULL PRIMARY KEY,"
"$ENGLISH_WORD TEXT,"
"$GERMAN_WORD TEXT,"
"$IS_FAV TEXT"
")");
});
还有DB中的add
函数,你应该选择当它面对一个重复的行(这里是Word)时应该做什么,有一些选项,一个可以是替换它,它应该改变像这样:
//add new words
Future<int> add(Word word) async {
final db = await database;
var response = await db.insert(TABLE, word.toMap(), conflictAlgorithm: ConflictAlgorithm.replace);
return response;
}
我希望这就是您要找的东西。