Lao Meng's Guide:前回の記事では、AndroidとiOSのファイルディレクトリシステムについて説明しました。この記事では、SQLiteを使用してデータを保存する方法について説明しました。貢献は大歓迎です:http://laomengit.com/plan/Contribution.html
データをローカルに保存することは、次のシナリオなど、アプリケーションの非常に重要な機能の1つです。ニュースまたはブログアプリケーションを開いてからホームページにアクセスします。ローカルに保存されたデータがない場合は、データを返す前にネットワーク経由でデータを取得する必要があります。 、ユーザーには空白のページが表示され、ニュースの一部がローカルに保存されている場合、データのこの部分が表示され、最新のデータが返されたときに更新できます。ユーザーエクスペリエンスの場合、2番目のエクスペリエンスの方が明らかに優れています。
SQLiteは、現在最も人気のあるローカルストレージフレームワークの1つです。この記事では、SQLiteを使用してデータを保存、クエリ、および削除する方法を紹介します。
SQLiteパブアドレス:https://pub.flutter-io.cn/packages/sqflite
SQLite Github:https://github.com/tekartik/sqflite
SQLiteの説明:https://www.sqlitetutorial.net/
データベースとSQLステートメントについて少し知識がある場合は、次の説明がわかりやすくなります。データベースとSQLステートメントについて何も知らない場合は、次の説明が理解しにくい場合があります。
最初にデータベースとSQLステートメントについて学ぶ必要がありますか?必要ではないと思います。アプリケーションで使用されるデータベースとSQLステートメントに関連する知識は、データベースを開く、テーブルを作成する、SQLクエリステートメント、更新ステートメント、削除ステートメントなど、非常に基本的なものです。これらはすべて固定形式です。固定ステートメントを覚えておいてください。 OK。
依存関係を追加する
SQLiteは、システムにFlutterが付属しているのではなく、pubspec.yaml
依存関係ファイルを追加するためのサードパーティのプラグインプロジェクトです。
dependencies:
sqflite: ^1.3.1
path_provider: ^1.6.11
注文の実行:
flutter pub get
SQLiteを使用してデータベースを作成する場合、パラメーターとしてローカルパスが必要になるため、path_provider
プラグインを追加してローカルパスを取得します。
SQLiteアクセスを作成するためのシングルトンモード
SQLiteの使用は、必ずしもシングルトンモードを使用するわけではありません。シングルトンモードは、アプリケーション全体が1つのデータベースインスタンスとグローバルアクセスのみを持つようにするためのものです。
class DBProvider{
static final DBProvider _singleton = DBProvider._internal();
factory DBProvider() {
return _singleton;
}
DBProvider._internal();
}
データベースを初期化します
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
class DBProvider {
static final DBProvider _singleton = DBProvider._internal();
factory DBProvider() {
return _singleton;
}
DBProvider._internal();
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, 'dbName');
return await openDatabase(path,
version: 1, onCreate: _onCreate, onUpgrade: _onUpgrade);
}
///
/// 创建Table
///
Future _onCreate(Database db, int version) async {}
///
/// 更新Table
///
Future _onUpgrade(Database db, int oldVersion, int newVersion) async {}
}
テーブルの作成、テーブルはテーブルを表し、下にユーザーテーブルを作成します。テーブルの列には、ID(一意の識別子)、名前(名前)、年齢(年齢)、性別(性別)があります。
///
/// 创建Table
///
Future _onCreate(Database db, int version) async {
return await db.execute("CREATE TABLE User ("
"id integer primary key AUTOINCREMENT,"
"name TEXT,"
"age TEXT,"
"sex integer"
")");
}
データを保存する
まず、データストレージ用のユーザーモデルクラスを作成します。
class User {
int id;
String name;
int age;
int sex;
User({this.id, this.name, this.age, this.sex});
User.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
age = json['age'];
sex = json['sex'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['age'] = this.age;
data['sex'] = this.sex;
return data;
}
}
データの保存:
Future saveData(User user) async {
var _db = await db;
return await _db.insert('User', user.toJson());
}
ケース:名前、年齢、性別を入力し、[保存]をクリックします
class _AddUser extends StatefulWidget {
@override
__AddUserState createState() => __AddUserState();
}
class __AddUserState extends State<_AddUser> {
String _radioGroupValue = '0';
TextEditingController _nameController;
TextEditingController _ageController;
@override
void initState() {
super.initState();
_nameController = TextEditingController();
_ageController = TextEditingController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('保存数据'),
),
body: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('姓名:'),
Flexible(
child: TextField(
controller: _nameController,
),
),
],
),
Row(
children: <Widget>[
Text('年龄:'),
Flexible(
child: TextField(
controller: _ageController,
),
),
],
),
Row(
children: <Widget>[
Text('性别:'),
Flexible(
child: RadioListTile(
title: Text('男'),
value: '0',
groupValue: _radioGroupValue,
onChanged: (value) {
setState(() {
_radioGroupValue = value;
});
},
),
),
Flexible(
child: RadioListTile(
title: Text('女'),
value: '1',
groupValue: _radioGroupValue,
onChanged: (value) {
setState(() {
_radioGroupValue = value;
});
},
),
),
],
),
Builder(
builder: (context) {
return RaisedButton(
child: Text('保存'),
onPressed: () async {
var user = User(
name: '${_nameController.text}',
age: int.parse('${_ageController.text}'),
sex: int.parse('$_radioGroupValue'));
int result = await DBProvider().saveData(user);
if (result > 0) {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('保存数据成功,result:$result'),
));
} else {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('保存数据失败,result:$result'),
));
}
},
);
},
)
],
),
);
}
}
SQLステートメントを使用してデータを保存します。
Future rawInsert(User user) async {
var _db = await db;
return await _db.rawInsert(
'INSERT Into User (name,age,sex) VALUES (?,?,?)',[user.name,user.age,user.sex]);
}
クエリデータ
すべてのデータを照会します。
Future<List<User>> findAll() async {
var _db = await db;
List<Map<String, dynamic>> result = await _db.query('User');
return result.isNotEmpty ? result.map((e) {
return User.fromJson(e);
}).toList():[];
}
クエリされたデータをテーブルに表示します。
class DatabaseDemo extends StatefulWidget {
@override
_DatabaseDemoState createState() => _DatabaseDemoState();
}
class _DatabaseDemoState extends State<DatabaseDemo> {
List<User> _list = [];
@override
void initState() {
super.initState();
_loadData();
}
_loadData() async {
_list = await DBProvider().findAll();
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Sqlite Demo'),
),
body: Column(
children: <Widget>[
Row(
children: <Widget>[
RaisedButton(
child: Text('查询数据'),
onPressed: (){
_loadData();
},
),
RaisedButton(
child: Text('添加数据'),
onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context){
return _AddUser();
}));
},
),
],
),
Table(
children: [
TableRow(children: [
TableCell(child: Text('id')),
TableCell(child: Text('姓名')),
TableCell(child: Text('年龄')),
TableCell(child: Text('性别')),
]),
..._list.map((user) {
return TableRow(children: [
TableCell(child: Text('${user.id}')),
TableCell(child: Text('${user.name}')),
TableCell(child: Text('${user.age}')),
TableCell(child: Text(user.sex == 0 ? '男' : '女')),
]);
}).toList()
],
)
],
),
);
}
}
12歳のデータのクエリなど、条件に従ってクエリを実行します。
Future<List<User>> find(int age) async {
var _db = await db;
List<Map<String, dynamic>> result =
await _db.query('User', where: 'age = ?', whereArgs: [age]);
return result.isNotEmpty ? result.map((e) {
return User.fromJson(e);
}).toList():[];
}
使用する:
_loadData() async {
_list = await DBProvider().find(12);
setState(() {});
}
データの更新
ユーザーIDに従ってデータを更新します。
Future<int> update(User user) async {
var _db = await db;
return await _db
.update('User', user.toJson(), where: 'id = ?', whereArgs: [user.id]);
}
データを変更するには、ページにジャンプします。
RaisedButton(
child: Text('修改第一行数据'),
onPressed: () {
if (_list.length > 1) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return _AddUser(
user: _list[0],
);
}));
}
},
),
変更したデータを保存します。
RaisedButton(
child: Text('保存'),
onPressed: () async {
var user = User(
name: '${_nameController.text}',
age: int.parse('${_ageController.text}'),
sex: int.parse('$_radioGroupValue'));
if (widget.user == null) {
_saveData(context,user);
} else {
_updateData(context,user);
}
},
)
_updateData(BuildContext context,User user) async {
user.id = widget.user.id;
int result = await DBProvider().update(user);
if (result > 0) {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('修改数据成功,result:$result'),
));
} else {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('修改数据失败,result:$result'),
));
}
}
データを削除する
IDに基づいて適格なデータを削除します。
Future<int> delete(int id) async {
var _db = await db;
return await _db.delete('User', where: 'id = ?', whereArgs: [id]);
}
データの最初の行を削除し、削除が成功した後にデータを更新します。
RaisedButton(
child: Text('删除第一行数据'),
onPressed: () async {
if (_list.length > 0) {
await DBProvider().delete(_list[0].id);
_loadData();
}
},
),
すべてのデータを削除します。
Future<int> deleteAll() async {
var _db = await db;
return await _db.delete('User');
}
総括する
SQLiteの基本的な使用法を紹介しました。データの追加、削除、変更、クエリが最も頻繁に使用されます。SQLiteには、グループ化や共同クエリなど、あまり使用されない高度なクエリステートメントもいくつかあります。
SQLiteが正常に作成されると、db_name.dbファイルがローカルに作成されます。ファイルディレクトリは、データベースが初期化されたときに設定されたディレクトリです。
と通信する
と通信する
Laomeng Flutterブログ(330コントロールの使用法+実際の戦闘紹介シリーズ):http://laomengit.com
Flutter交換グループ(WeChat:laomengit)に参加し、パブリックアカウント[Lao Meng Flutter]をフォローすることを歓迎します: