Привет, Хабр! Представляем вашему вниманию перевод статьи «Using SQLite in Flutter».
Сохранение данных очень важно для пользователей, так как нецелесообразно грузить одни и те же данные из сети. Разумнее будет сохранить их локально.
В этой статье я продемонстрирую как сделать это, используя SQLite, в Flutter-e
dependencies:
flutter:
sdk: flutter
sqflite: any
path_provider: any
class DBProvider {
DBProvider._();
static final DBProvider db = DBProvider._();
}
static Database _database;
Future<Database> get database async {
if (_database != null)
return _database;
// if _database is null we instantiate it
_database = await initDB();
return _database;
}
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "TestDB.db");
return await openDatabase(path, version: 1, onOpen: (db) {
}, onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE Client ("
"id INTEGER PRIMARY KEY,"
"first_name TEXT,"
"last_name TEXT,"
"blocked BIT"
")");
});
}
/// ClientModel.dart
import 'dart:convert';
Client clientFromJson(String str) {
final jsonData = json.decode(str);
return Client.fromJson(jsonData);
}
String clientToJson(Client data) {
final dyn = data.toJson();
return json.encode(dyn);
}
class Client {
int id;
String firstName;
String lastName;
bool blocked;
Client({
this.id,
this.firstName,
this.lastName,
this.blocked,
});
factory Client.fromJson(Map<String, dynamic> json) => new Client(
id: json["id"],
firstName: json["first_name"],
lastName: json["last_name"],
blocked: json["blocked"],
);
Map<String, dynamic> toJson() => {
"id": id,
"first_name": firstName,
"last_name": lastName,
"blocked": blocked,
};
}
newClient(Client newClient) async {
final db = await database;
var res = await db.rawInsert(
"INSERT Into Client (id,first_name)"
" VALUES (${newClient.id},${newClient.firstName})");
return res;
}
newClient(Client newClient) async {
final db = await database;
var res = await db.insert("Client", newClient.toMap());
return res;
}
newClient(Client newClient) async {
final db = await database;
//get the biggest id in the table
var table = await db.rawQuery("SELECT MAX(id)+1 as id FROM Client");
int id = table.first["id"];
//insert to the table using the new id
var raw = await db.rawInsert(
"INSERT Into Client (id,first_name,last_name,blocked)"
" VALUES (?,?,?,?)",
[id, newClient.firstName, newClient.lastName, newClient.blocked]);
return raw;
}
getClient(int id) async {
final db = await database;
var res =await db.query("Client", where: "id = ?", whereArgs: [id]);
return res.isNotEmpty ? Client.fromMap(res.first) : Null ;
}
getAllClients() async {
final db = await database;
var res = await db.query("Client");
List<Client> list =
res.isNotEmpty ? res.map((c) => Client.fromMap(c)).toList() : [];
return list;
}
getBlockedClients() async {
final db = await database;
var res = await db.rawQuery("SELECT * FROM Client WHERE blocked=1");
List<Client> list =
res.isNotEmpty ? res.toList().map((c) => Client.fromMap(c)) : null;
return list;
}
updateClient(Client newClient) async {
final db = await database;
var res = await db.update("Client", newClient.toMap(),
where: "id = ?", whereArgs: [newClient.id]);
return res;
}
blockOrUnblock(Client client) async {
final db = await database;
Client blocked = Client(
id: client.id,
firstName: client.firstName,
lastName: client.lastName,
blocked: !client.blocked);
var res = await db.update("Client", blocked.toMap(),
where: "id = ?", whereArgs: [client.id]);
return res;
}
deleteClient(int id) async {
final db = await database;
db.delete("Client", where: "id = ?", whereArgs: [id]);
}
deleteAll() async {
final db = await database;
db.rawDelete("Delete * from Client");
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Flutter SQLite")),
body: FutureBuilder<List<Client>>(
future: DBProvider.db.getAllClients(),
builder: (BuildContext context, AsyncSnapshot<List<Client>> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Client item = snapshot.data[index];
return ListTile(
title: Text(item.lastName),
leading: Text(item.id.toString()),
trailing: Checkbox(
onChanged: (bool value) {
DBProvider.db.blockClient(item);
setState(() {});
},
value: item.blocked,
),
);
},
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () async {
Client rnd = testClients[math.Random().nextInt(testClients.length)];
await DBProvider.db.newClient(rnd);
setState(() {});
},
),
);
}
List<Client> testClients = [
Client(firstName: "Raouf", lastName: "Rahiche", blocked: false),
Client(firstName: "Zaki", lastName: "oun", blocked: true),
Client(firstName: "oussama", lastName: "ali", blocked: false),
];
return Dismissible(
key: UniqueKey(),
background: Container(color: Colors.red),
onDismissed: (direction) {
DBProvider.db.deleteClient(item.id);
},
child: ListTile(...),
);
class ClientsBloc {
ClientsBloc() {
getClients();
}
final _clientController = StreamController<List<Client>>.broadcast();
get clients => _clientController.stream;
dispose() {
_clientController.close();
}
getClients() async {
_clientController.sink.add(await DBProvider.db.getAllClients());
}
}
blockUnblock(Client client) {
DBProvider.db.blockOrUnblock(client);
getClients();
}
delete(int id) {
DBProvider.db.deleteClient(id);
getClients();
}
add(Client client) {
DBProvider.db.newClient(client);
getClients();
}
К сожалению, не доступен сервер mySQL