Orientação gerada a partir de informações públicas. Apenas para referência.
Sqlcool é um pacote Flutter/Dart que simplifica o trabalho com bancos de dados SQLite ao fornecer fluxos reativos para alterações no banco de dados, padrões internos de seleção do bloc e suporte para modelos de banco de dados personalizados. Permite sincronização em tempo real de dados e consultas eficientes com mínimo código repetitivo. Projetado para desenvolvedores que buscam uma solução leve e intuitiva para armazenamento local persistente de dados em aplicativos Flutter, o Sqlcool se integra perfeitamente aos paradigmas de programação reativa. O pacote enfatiza a facilidade de uso, mantendo flexibilidade para operações complexas no banco de dados.
Casos de uso
Sincronização de dados em tempo real em aplicativos com foco em offline
Atualizações de interface reativas com base em alterações no banco de dados
Gerenciando estado local com modelos de banco de dados estruturados
Criando formulários com carregamento dinâmico de dados
Implementando camadas de cache com SQLite
Simplificando operações CRUD com modelos personalizados
Principais recursos
Fluxos reativos para notificações de alterações no banco de dados
Padrão de bloco de seleção embutido para gerenciamento de estado
Suporte para definições de modelo de banco de dados personalizadas
API simples para consultas e mutações
Mapeamento de modelo seguro por tipo automaticamente
Leve e dependências mínimas
Indicado para
Desenvolvedores construindo aplicativos Flutter com capacidade offline
Equipes usando gerenciamento reativo de estado
Projetos que exigem atualizações em tempo real do banco de dados
Aplicativos que precisam de persistência de dados locais estruturados
Iniciantes aprendendo SQLite no Flutter
Aplicativos com interações frequentes de dados locais
Considerações
Limitado apenas ao SQLite (nenhum outro banco de dados)
Sem tratamento de migração embutido (manual ou ferramentas externas necessárias)
Pode exigir configuração adicional para alterações complexas no esquema
Não ideal para operações de banco de dados do lado do servidor em grande escala
Mais adequado para casos de uso móvel e desktop
Requer conhecimento sobre conceitos de programação reativa
README original
Snapshot do README original do repositório-fonte vinculado. Consulte o repositório para o conteúdo mais recente.
Sqlcool
A database helper library for Sqflite. Forget about implementation details and focus on the business logic.
A stream of database change events is available. Inspired by Rethinkdb
import'dart:async';
import'package:sqlcool/sqlcool.dart';
StreamSubscription changefeed;
changefeed = db.changefeed.listen((change) {
print("Change in the database:");
print("Query: ${change.query}");
if (change.type == DatabaseChange.update) {
print("${change.value} items updated");
}
});
// Dispose the changefeed when finished using it
changefeed.cancel();
Reactive select bloc
The bloc will rebuild itself on any database change because of the reactive
parameter set to true:
import'package:flutter/material.dart';
import'package:sqlcool/sqlcool.dart';
class_PageSelectBlocStateextendsState<PageSelectBloc> {
SelectBloc bloc;
@overridevoidinitState() {
super.initState();
this.bloc = SelectBloc(
table: "items", orderBy: "name", reactive: true);
}
@overridevoiddispose() {
bloc.dispose();
super.dispose();
}
@overrideWidgetbuild(BuildContext context) {
returnScaffold(
appBar: AppBar(title: Text("My app")),
body: StreamBuilder<List<Map>>(
stream: bloc.items,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
// the select query has not found anythingif (snapshot.data.length == 0) {
returnCenter(child: constText("No data"));
}
// the select query has resultsreturnListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
var item = snapshot.data[index];
returnListTile(
title: GestureDetector(
child: Text(item["name"]),
onTap: () => someFunction()),
);
});
} else {
// the select query is still runningreturnCircularProgressIndicator();
}
}),
);
}
}
classPageSelectBlocextendsStatefulWidget{
@override_PageSelectBlocStatecreateState() => _PageSelectBlocState();
}
Database models
New in 4.0.0: define models that have database methods. The main
advantage of this is to use only typed model data and avoid the
type conversions from maps for every query. It directly plugs custom
models into the database. Example:
In schema.dart:
final carTable = DbTable("car")
..varchar("name")
..integer("max_speed")
..real("price")
..integer("year")
..boolean("is_4wd", defaultValue: false)
..foreignKey("manufacturer", onDelete: OnDelete.cascade);
final manufacturerTable = DbTable("manufacturer")..varchar("name");
In car_model.dart:
import'package:sqlcool/sqlcool.dart';
// the database schemaimport'schema.dart';
// another modelimport'manufacturer_model.dart';
classCarwithDbModel{
Car(
{this.id,
this.name,
this.maxSpeed,
this.price,
this.year,
this.is4wd,
this.manufacturer});
/// define some class propertiesfinalString name;
finalint maxSpeed;
finaldouble price;
finalDateTime year;
finalbool is4wd;
// this is a foreign key to another modelManufacturer manufacturer;
/// [DbModel] required overrides@overrideint id;
/// the [Db] used/// pass it your main db@overrideDbget db => db;
/// the table schema representation/// check example/pages/dbmodels/schema.dart@overrideDbTableget table => carTable;
/// serialize a row to the database@overrideMap<String, dynamic> toDb() {
// we want the foreign key to be recordedassert(manufacturer?.id != null);
final row = <String, dynamic>{
"name": name,
"max_speed": maxSpeed,
"price": price,
"year": year.millisecondsSinceEpoch,
"is_4wd": is4wd,
"manufacturer": manufacturer.id
};
return row;
}
/// deserialize a row from database@overrideCarfromDb(Map<String, dynamic> map) {
final car = Car(
id: map["id"] asint,
name: map["name"].toString(),
maxSpeed: map["max_speed"] asint,
price: map["price"] asdouble,
year: DateTime.fromMillisecondsSinceEpoch(map["year"] asint),
is4wd: (map["is_4wd"].toString() == "true"),
);
// the key will be present only with join queries// in a simple select this data is not presentif (map.containsKey("manufacturer")) {
car.manufacturer =
Manufacturer().fromDb(map["manufacturer"] asMap<String, dynamic>);
}
return car;
}
/// Create a static join method for conveniencestaticFuture<List<Car>> selectRelated({String where, int limit}) async {
final cars = List<Car>.from(
awaitCar().sqlJoin(where: where, limit: limit, verbose: true));
return cars;
}
}
Then use the models:
/// car is an instance of [Car]await car.sqlInsert();
await car.sqlUpdate();
await car.sqlUpsert();
await car.sqlDelete();
final cars = Car.selectRelated(where: "speed>200");
// foreign keys are retrieved as model instancesprint(cars[0].manufacturer.name);