In native Android, some lightweight data (such as user login information, APP configuration information, etc.) will be written into SharedPreferences for storage, while in iOS, NSUserDefaults will be used for storage. Sqlite will be used to realize the requirement of adding, deleting, modifying and searching large quantities of data. There are also officially maintained plug-ins for Flutter to implement these functions.
Simple data persistence
Saving data to local disks is a common function of application programs, such as saving user login information and user configuration information. This information is usually saved using shared_preferences, which stores data as key-value pairs for Android and iOS. Shared_preferences is a third-party plugin that uses NSUserDefaults in iOS and SharedPreferences in Android.
Add the dependent
Add dependencies to the project’s pubspec.yaml file:
Dependencies: shared_preferences: ^ 2.0.10Copy the code
Execute command:
flutter pub get
Copy the code
Shared_preferences Supports the data types int, Double, bool, String, and stringList.
The sample code
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SaveDataPage extends StatefulWidget { @override State<StatefulWidget> createState() => SaveDataState(); } class SaveDataState extends State { final _textFieldController = TextEditingController(); var _storageString = ''; final SAVE_KEY = 'storage_key'; Future saveString() Async {SharedPreferences SharedPreferences = await SharedPreferences.getInstance(); sharedPreferences.setString( SAVE_KEY, _textFieldController.value.text.toString()); Future getString() Async {SharedPreferences SharedPreferences = await SharedPreferences.getInstance(); setState(() { if(sharedPreferences.getString(SAVE_KEY) ! = null) { _storageString = sharedPreferences.getString(SAVE_KEY)! ; }}); } @override Widget build(BuildContext context) {return Scaffold(appBar: appBar (title: const Text(' data store '),), body: Column(children: <Widget>[const Text("shared_preferences store ", textAlign: textalign.center), TextField(Controller: Textfieldcontroller,), MaterialButton(onPressed: saveString, Child: const Text(" store "), color: Color.pink,), MaterialButton(onPressed: getString, Child: const Text(" fetch "), color: LightGreen,), Text('shared_preferences store = $_storageString'),],),); }}Copy the code
The actual effect
Persistence of large amounts of complex data
To have a large amount of data to add, delete, change, check the demand, we thought of the database Sqlite. The database in Flutter is called Sqflite, not Sqlite. Sqflite is an Android and iOS database.
Add the dependent
Sqflite: ^ 2.0.1Copy the code
Execute command:
flutter pub get
Copy the code
Introduction to Usage
Insert data
There are two ways to insert data:
Future<int> insert(String table, Map<String, Object? > values, {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}); Future<int> rawInsert(String sql, [List<Object?>? arguments]);Copy the code
insert
Method the first parameter is the name of the table to be operated on, the second parameter map is the name and value of the field to be added, and the third parameter is the solution in case of a conflict. An example of an insert given by the official:
var value = {
'age': 18,
'name': 'Candy'
};
int id = await db.insert(
'table',
value,
conflictAlgorithm: ConflictAlgorithm.replace,
);
Copy the code
rawInsert
Method takes an insert as the first argumentsql
Statement, the second parameter represents the fill data. An example of an insert given by the official:
Int id1 = await database.rawInsert('INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');Copy the code
Query data
Querying data provides two methods:
Future<List<Map<String, Object? >>> query(String table, {bool? distinct, List<String>? columns, String? where, List<Object? >? whereArgs, String? groupBy, String? having, String? orderBy, int? limit, int? offset}); Future<List<Map<String, Object? >>> rawQuery(String sql, [List<Object?>? arguments]);Copy the code
query
The first parameter of the method is the table name of the operation, followed by optional parameters indicating whether to de-duplicate, query field, WHERE clause, where clause placeholder parameter value, how to group, which row groups to contain, how to sort, the number of rows to query, and the offset bit to query. All but the table names and query fields are non-mandatory. Official query examples:
List<Map> maps = await db.query(tableTodo, columns: ['columnId', 'columnDone', 'columnTitle'], where: 'columnId = ? ', whereArgs: [id]);Copy the code
rawQuery
The first parameter to the method is a query SQL statement. Official query examples:
List<Map> list = await database.rawQuery('SELECT * FROM Test');
Copy the code
Update the data
Update the data in the database and return the number of changes. There are also two methods provided here.
Future<int> rawUpdate(String sql, [List<Object?>? arguments]); Future<int> update(String table, Map<String, Object? > values, {String? where, List<Object? >? whereArgs, ConflictAlgorithm? conflictAlgorithm});Copy the code
rawUpdate
The first parameter of the method is an update SQL statement and the second parameter represents the updated data. Official query examples:
int count = await database.rawUpdate( 'UPDATE Test SET name = ? , value = ? WHERE name = ? ', ['updated name', '9876', 'some name']);Copy the code
update
Method the first parameter is the name of the operation table, the second parameter is the modified field and the corresponding value, followed by the WHERE statement, where clause placeholder parameter value, and the resolution of the conflict. Official query examples:
int count = await db.update(tableTodo, todo.toMap(), where: '$columnId = ? ', whereArgs: [todo.id]);Copy the code
Delete the data
There are also two ways to delete data, returning the number of deletions.
Future<int> rawDelete(String sql, [List<Object?>? arguments]); Future<int> delete(String table, {String? where, List<Object? >? whereArgs});Copy the code
rawDelete
The first parameter of the method is a delete SQL statement and the second parameter represents the fill data. Official query examples:
int count = await database.rawDelete('DELETE FROM Test WHERE name = ? ', ['another name']);Copy the code
delete
The first argument to the method is the table name of the operation, followed by optional arguments representing the WHERE clause and where clause placeholder parameter values. Official query examples:
int count = await db.delete(tableTodo, where: 'columnId = ?', whereArgs: [id]);
Copy the code
For example
Defines a Person object, through the encapsulation database definition of a class DBProvider to achieve the increase, delete, change, search.
Create SQLite in singleton mode
SQLite static final dbprovider_singleton = dbprovider._internal (); factory DBProvider() { return _singleton; } DBProvider._internal();Copy the code
Complete create database, including add, delete, change, check the code
import 'dart:io'; import 'package:path_provider/path_provider.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; SQLite 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 {// Get Directory documentsDirectory = await for Database files getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, 'demo.db'); Return await openDatabase(path, version: 1, onCreate: _onCreate); } // create a Database table Future _onCreate(Database db, int version) async { return await db.execute(''' CREATE TABLE $tablePerson ( $columnId INTEGER PRIMARY KEY, $columnName TEXT, $columnSex TEXT, $columnAge INTEGER, '''); Future<Person> insert(Person Person) async {person.id = await _db! .insert(tablePerson, person.toMap()); return person; } Future<List<Person>? > queryAll() async { List<Map> maps = await _db! .query(tablePerson, columns: [ columnId, columnName, columnSex, columnAge ]); if (maps.isEmpty) { return null; } List<Person> books = []; for (int i = 0; i < maps.length; i++) { books.add(Person.fromMap(maps[i])); } return books; } Future<Person? > getBook(int id) async { List<Map> maps = await _db! .query(tablePerson, columns: [ columnId, columnName, columnSex, columnAge ], where: '$columnId = ? ', whereArgs: [id]); if (maps.isNotEmpty) { return Person.fromMap(maps.first); } return null; Future<int> delete(int ID) async {return await _db! .delete(tablePerson, where: '$columnId = ?', whereArgs: [id]); Future<int> Update (Person Person) async {return await _db! .update(tablePerson, person.toMap(), where: '$columnId = ? ', whereArgs: [person.id]); }}Copy the code
Code for the Person class
const String tablePerson = 'person'; const String columnId = '_id'; const String columnName = 'name'; const String columnSex = 'sex'; const String columnAge = 'age'; class Person { int? id; String? name; String? sex; int? age; Person({required this.id, required this.name, required this.sex, required this.age}); Map<String, dynamic> toMap() { var map = <String, dynamic>{ columnName: name, columnSex: sex, columnAge: age }; map[columnId] = id; return map; } Person.fromMap(Map<dynamic, dynamic> map) { id = map[columnId]; name = map[columnName]; sex = map[columnSex]; age = map[columnAge]; }}Copy the code
The basic usage of SQLite has been described above. Adding, deleting, modifying, and querying data is frequently used. SQLite also has some other uses that can be extended according to business requirements.