Similar presentations:
Работа с файлами и данными
1.
Работа с файлами иданными
2.
File classvar myFile = File('file.txt');
Класс File содержит методы для управления
файлами и их содержимым. Используя методы
этого класса, вы можете открывать и закрывать
файлы, выполнять чтение и запись из них, создавать
и удалять их, а также проверять их существование.
3.
4.
Read from a fileimport 'dart:async';
import 'dart:io';
void main() {
File('file.txt').readAsString().then((String
contents) {
print(contents);
});
}
5.
import 'dart:io';import 'dart:convert';
import 'dart:async';
void main() async {
final file = File('file.txt');
Stream<String> lines = file.openRead()
.transform(utf8.decoder)
// Decode bytes to UTF-8.
.transform(LineSplitter()); // Convert stream to individual lines.
try {
await for (var line in lines) {
print('$line: ${line.length} characters');
}
print('File is now closed.');
} catch (e) {
print('Error: $e');
}
6.
Write to a fileimport 'dart:io';
void main() async {
final filename = 'file.txt';
var file = await
File(filename).writeAsString('some content');
// Do something with the file.
}
7.
IOSinkIOSink предназначен для записи байтов.
Строки, записанные с помощью write или
writeCharCode, будут преобразованы в
байты с использованием кодировки.
Целочисленные данные, добавленные с
помощью add или addStream, будут
обрабатываться как байтовые данные и
будут усечены до 8-разрядных значений
без знака, как при использовании
int.toUnsigned.
8.
import 'dart:io';void main() {
var file = File('file.txt');
var sink = file.openWrite();
sink.write('FILE ACCESSED ${DateTime.now()}\n');
// Close the IOSink to free system resources.
sink.close();
}
9.
Использование асинхронных методовimport 'dart:io';
void main() async {
final file = File('file.txt');
var length = await file.length();
print(length);
}
10.
path_provider11.
Поддерживаемые платформы и путиDirectory
Android
macOS
Windows
Temporary
✔
✔
✔
✔
✔
Application
Support
✔
✔
✔
✔
✔
Application
Library
❌
✔
❌
✔
❌
Application
Documents
✔
✔
✔
✔
✔
Application
Cache
✔
✔
✔
✔
✔
External Storage
✔
❌
❌
❌
❌
External Cache
Directories
✔
❌
❌
❌
❌
External Storage
Directories
✔
❌
❌
❌
❌
✔ (❌ 2,12)
✔
✔
✔
✔
Downloads
iOS
Linux
12.
Тестированиеpath_provider теперь использует PlatformInterface, что
означает, что не все платформы используют единую
реализацию на основе PlatformChannel. С учетом этого
изменения тесты должны быть обновлены, чтобы
имитировать PathProviderPlatform, а не
PlatformChannel.
13.
const String kTemporaryPath = 'temporaryPath';setUp(() async {
PathProviderPlatform.instance = FakePathProviderPlatform();
});
test('getTemporaryDirectory', () async {
final Directory result = await getTemporaryDirectory();
expect(result.path, kTemporaryPath);
});
14.
class FakePathProviderPlatform extends Fakewith MockPlatformInterfaceMixin
implements PathProviderPlatform {
@override
Future<String?> getTemporaryPath() async {
return kTemporaryPath;
}
15.
TemporaryDirectoryFuture<Directory> getTemporaryDirectory() async {
final String? path = await
_platform.getTemporaryPath();
if (path == null) {
throw MissingPlatformDirectoryException(
'Unable to get temporary directory');
}
return Directory(path);
}
16.
ApplicationDocumentsDirectoryFuture<Directory> getApplicationDocumentsDirectory()
async {
final String? path = await
_platform.getApplicationDocumentsPath();
if (path == null) {
throw MissingPlatformDirectoryException(
'Unable to get application documents
directory');
}
return Directory(path);
}
17.
ApplicationSupportDirectoryFuture<Directory> getApplicationSupportDirectory() async
{
final String? path = await
_platform.getApplicationSupportPath();
if (path == null) {
throw MissingPlatformDirectoryException(
'Unable to get application support directory');
}
return Directory(path);
}
18.
LibraryDirectoryFuture<Directory> getLibraryDirectory() async {
final String? path = await
_platform.getLibraryPath();
if (path == null) {
throw
MissingPlatformDirectoryException('Unable to get
library directory');
}
return Directory(path);
}
19.
ExternalStorageDirectoryFuture<Directory?> getExternalStorageDirectory()
async {
final String? path = await
_platform.getExternalStoragePath();
if (path == null) {
return null;
}
return Directory(path);
}
20.
ExternalStorageDirectoriesFuture<List<Directory>?> getExternalStorageDirectories({
/// Optional parameter. See [StorageDirectory] for more
informations on
/// how this type translates to Android storage directories.
StorageDirectory? type,
}) async {
final List<String>? paths =
await _platform.getExternalStoragePaths(type: type);
if (paths == null) {
return null;
}
return paths.map((String path) => Directory(path)).toList();
}
21.
ExternalCacheDirectoriesFuture<List<Directory>?>
getExternalCacheDirectories() async {
final List<String>? paths = await
_platform.getExternalCachePaths();
if (paths == null) {
return null;
}
return paths.map((String path) =>
Directory(path)).toList();
}
22.
ApplicationCacheDirectoryFuture<Directory> getApplicationCacheDirectory()
async {
final String? path = await
_platform.getApplicationCachePath();
if (path == null) {
throw MissingPlatformDirectoryException(
'Unable to get application cache
directory');
}
return Directory(path);
}
23.
DownloadsDirectoryFuture<Directory?> getDownloadsDirectory() async
{
final String? path = await
_platform.getDownloadsPath();
if (path == null) {
return null;
}
return Directory(path);
}
24.
shared_preferences25.
SharedPreferences и его варианты• SharedPreferences
• SharedPreferencesAsync
• SharedPreferencesWithCache
26.
Cache and async or sync getters[SharedPreferences] и [SharedPreferencesWithCache]
используют локальный кэш для хранения настроек.
Это позволяет выполнять синхронные вызовы get
после того, как при первоначальном вызове setup
настройки будут получены с платформы.
27.
Cache and async or sync gettersОднако с кэшем также могут возникнуть проблемы:
• Если вы используете shared_preferences из нескольких изолятов,
поскольку каждый изолят имеет свой собственный синглтон и кэш.
• Если вы используете shared_preferences в нескольких экземплярах
(включая те, которые созданы плагинами, создающими фоновые
контексты на мобильных устройствах, такими как firebase_messaging).
• Если вы изменяете базовое хранилище системных настроек с помощью
чего-то другого, кроме плагина shared_preferences, например, нативного
кода.
28.
Cache and async or sync getters[SharedPreferencesAsync]
не
использует
локальный кэш, из-за чего все вызовы становятся
асинхронными для решения для хранения данных
на хост-платформах. Это может быть менее
производительным,
но
всегда
должно
предоставлять самые свежие данные, хранящиеся
на собственной платформе, независимо от того,
какой процесс использовался для их хранения.
29.
Storage location by platformPlatform
Location
Android
SharedPreferences
iOS
NSUserDefaults
Linux
In the XDG_DATA_HOME
directory
macOS
NSUserDefaults
Web
LocalStorage
Windows
In the roaming AppData directory
30.
Запись данных// Obtain shared preferences.
final SharedPreferences prefs = await
SharedPreferences.getInstance();
// Save an integer value to 'counter' key.
await prefs.setInt('counter', 10);
// Save an boolean value to 'repeat' key.
await prefs.setBool('repeat', true);
// Save an double value to 'decimal' key.
await prefs.setDouble('decimal', 1.5);
// Save an String value to 'action' key.
await prefs.setString('action', 'Start');
// Save an list of strings to 'items' key.
await prefs.setStringList('items', <String>['Earth', 'Moon',
'Sun']);
31.
Чтение данных// Try reading data from the 'counter' key. If it doesn't exist,
returns null.
final int? counter = prefs.getInt('counter');
// Try reading data from the 'repeat' key. If it doesn't exist,
returns null.
final bool? repeat = prefs.getBool('repeat');
// Try reading data from the 'decimal' key. If it doesn't exist,
returns null.
final double? decimal = prefs.getDouble('decimal');
// Try reading data from the 'action' key. If it doesn't exist,
returns null.
final String? action = prefs.getString('action');
// Try reading data from the 'items' key. If it doesn't exist,
returns null.
final List<String>? items = prefs.getStringList('items');
32.
Удаление данных// Remove data for the 'counter' key.
await prefs.remove('counter');
33.
SharedPreferencesAsyncfinal SharedPreferencesAsync asyncPrefs = SharedPreferencesAsync();
await asyncPrefs.setBool('repeat', true);
await asyncPrefs.setString('action', 'Start');
final bool? repeat = await asyncPrefs.getBool('repeat');
final String? action = await asyncPrefs.getString('action');
await asyncPrefs.remove('repeat');
await asyncPrefs.clear(allowList: <String>{'action', 'repeat'});
34.
final SharedPreferencesWithCache prefsWithCache =await SharedPreferencesWithCache.create(
cacheOptions: const SharedPreferencesWithCacheOptions(
// When an allowlist is included, any keys that aren't included cannot be used.
allowList: <String>{'repeat', 'action'},
),
);
await prefsWithCache.setBool('repeat', true);
await prefsWithCache.setString('action', 'Start');
final bool? repeat = prefsWithCache.getBool('repeat');
final String? action = prefsWithCache.getString('action');
await prefsWithCache.remove('repeat');
await prefsWithCache.clear();
35.
Несколько экземпляров• Если вы используете shared_preferences из нескольких изолятов,
поскольку каждый изолят имеет свой собственный синглтон
SharedPreferences и кэш.
• Если вы используете shared_preferences в нескольких engine
instances (включая те, которые созданы плагинами, создающими
фоновые контексты на мобильных устройствах, такими как
firebase_messaging).
• Если вы изменяете базовое хранилище системных настроек с
помощью чего-то другого, кроме плагина shared_preferences,
например, машинного кода.
36.
Migrating from SharedPreferences toSharedPreferencesAsync/WithCache
В настоящее время переход с более старого API
[SharedPreferences] на более новый SharedPreferencesAsync]
или [SharedPreferencesWithCache] необходимо выполнять
вручную. Простой формой этого может быть получение всех
настроек с помощью [SharedPreferences] и добавление их
обратно с помощью [SharedPreferencesAsync], а затем
сохранение предпочтений, указывающих на то, что миграция
была выполнена, чтобы в будущих запусках миграция не
повторялась.
37.
Adding, Removing, or changing prefixes onSharedPreferences
По умолчанию класс SharedPreferences будет считывать (и
записывать) только те настройки, которые начинаются с префикса
flutter.. Все это обрабатывается плагином самостоятельно и не
требует добавления этого префикса вручную. В качестве
альтернативы,
SharedPreferences
можно
настроить
на
использование любого префикса, добавив вызов setPrefix перед
созданием любых экземпляров SharedPreferences. Вызов setPrefix
после создания экземпляра SharedPreferences приведет к сбою.
Установка префикса в пустую строку " позволит получить доступ
ко всем настройкам, созданным любыми версиями приложения,
отличными от flutter (для перехода с нативного приложения на
flutter).
38.
Adding, Removing, or changing prefixes onSharedPreferences
Если префиксу присвоено значение, такое как "", которое
приводит к считыванию значений, которые изначально не были
сохранены в SharedPreferences, инициализация SharedPreferences
может завершиться ошибкой, если какое-либо из значений
относится
к
типам,
которые
не
поддерживаются
SharedPreferences. В этом случае вы можете установить список
разрешений, содержащий только настройки поддерживаемых
типов. Если вы решите полностью удалить префикс, вы все равно
сможете получить доступ к ранее созданным настройкам,
вручную добавив предыдущий префикс flutter. в начало клавиши
настройки.
39.
TestingВ тестах вы можете заменить стандартную
реализацию SharedPreferences на имитационную
реализацию с начальными значениями. Эта
реализация доступна только в памяти и не будет
сохранять значения в обычном хранилище
предпочтений.
final Map<String, Object> values = <String, Object>{'counter': 1};
SharedPreferences.setMockInitialValues(values);
40.
SQFLITEimport 'package:sqflite/sqflite.dart';
41.
Открытие и закрытие БДvar db = await openDatabase('my_db.db');
Многие приложения используют одну базу данных,
и им никогда не потребуется ее закрывать (она
будет закрыта при завершении работы
приложения). Если вы хотите освободить ресурсы,
вы можете закрыть базу данных.
await db.close();
42.
Raw SQL queriesvar databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'demo.db');
await deleteDatabase(path);
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute(
'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value
INTEGER, num REAL)');
});
43.
Raw SQL queriesawait database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Test(name, value, num) VALUES("some name", 1234,
456.789)');
print('inserted1: $id1');
int id2 = await txn.rawInsert(
'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)',
['another name', 12345678, 3.1416]);
print('inserted2: $id2');
});
44.
Raw SQL queriesint count = await database.rawUpdate(
'UPDATE Test SET name = ?, value = ? WHERE name = ?',
['updated name', '9876', 'some name']);
print('updated: $count');
45.
Raw SQL queriesList<Map> list = await database.rawQuery('SELECT * FROM Test');
List<Map> expectedList = [
{'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789},
{'name': 'another name', 'id': 2, 'value': 12345678, 'num':
3.1416}
];
print(list);
print(expectedList);
assert(const DeepCollectionEquality().equals(list, expectedList));
46.
Raw SQL queriescount = Sqflite
.firstIntValue(await database.rawQuery('SELECT COUNT(*) FROM
Test'));
assert(count == 2);
count = await database
.rawDelete('DELETE FROM Test WHERE name = ?', ['another
name']);
assert(count == 1);
await database.close();
47.
SQL helpersfinal String tableTodo =
'todo';
final String columnId = '_id';
final String columnTitle =
'title';
final String columnDone =
'done'
class Todo {
int id;
String title;
bool done;
toMap() …..
fromMap(…)…
class TodoProvider {
Database db;
Future open(String path) async {
db = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute('''
create table $tableTodo (
$columnId integer primary key autoincrement,
$columnTitle text not null,
$columnDone integer not null)
''');
});
}
48.
SQL helpersFuture<int> delete(int id)
async {
return await
db.delete(tableTodo,
where: '$columnId = ?',
whereArgs: [id]);
}
Future<int> update(Todo
todo) async {
return await
db.update(tableTodo,
todo.toMap(),
where: '$columnId =
?', whereArgs: [todo.id]);
}
Future<Todo> insert(Todo todo) async {
todo.id = await db.insert(tableTodo, todo.toMap());
return todo;
}
Future<Todo> getTodo(int id) async {
List<Map> maps = await db.query(tableTodo,
columns: [columnId, columnDone, columnTitle],
where: '$columnId = ?',
whereArgs: [id]);
if (maps.length > 0) {
return Todo.fromMap(maps.first);
}
return null;
}
Future close() async => db.close();
49.
Read resultsList<Map<String, Object?>> records = await db.query('my_table');
Результирующие элементы доступны только для чтения
// get the first record
Map<String, Object?> mapRead = records.first;
// Update it in memory...this will throw an
exception
mapRead['my_column'] = 1;
// Crash... `mapRead` is read-only
50.
Transactionawait database.transaction((txn) async {
// Ok
await txn.execute('CREATE TABLE Test1 (id INTEGER PRIMARY KEY)');
// DON'T use the database object in a transaction
// this will deadlock!
await database.execute('CREATE TABLE Test2 (id INTEGER PRIMARY
KEY)');
});
51.
Batch supportbatch = db.batch();
batch.insert('Test', {'name': 'item'});
batch.update('Test', {'name': 'new_item'}, where: 'name = ?',
whereArgs: ['item']);
batch.delete('Test', where: 'name = ?', whereArgs: ['item']);
results = await batch.commit();
52.
await database.transaction((txn) async {var batch = txn.batch();
// ...
// commit but the actual commit will happen when the transaction is committed
// however the data is available in this transaction
await batch.commit();
// ...
});
await batch.commit(continueOnError: true);
53.
Table and column namesВ общем, лучше избегать использования ключевых слов SQLite для
имен сущностей. Если используется любое из следующих имен:
"add","all","alter","and","as","autoincrement","between","case","chec
k","collate","commit","constraint","create","default","deferrable","dele
te","distinct","drop","else","escape","except","exists","foreign","from",
"group","having","if","in","index","insert","intersect","into","is","isnull"
,"join","limit","not","notnull","null","on","or","order","primary","refere
nces","select","set","table","then","to","transaction","union","unique",
"update","using","values","when","where"
54.
db.rawQuery('SELECT * FROM "table"');db.query('table', columns: ['group'], where: '"group" = ?',
whereArgs: ['my_group']);
55.
Supported SQLite typesINTEGER
Dart type: int
Supported values: from -2^63 to 2^63 - 1
REAL
Dart type: num
TEXT
Dart type: String
BLOB
Dart type: Uint8List
56.
Current issuesИз-за способа работы транзакций в SQLite (потоки)
одновременные транзакции чтения и записи не
поддерживаются.
57.
sqflite_sqlcipherDatabase db = await openDatabase(
path,
password: "my password",
// onCreate, onUpgrade...
);
58.
Hive59.
• Кросс-платформенность — так как на чистом Dart и нет нативныхзависимостей — mobile, desktop, browser.
• Высокая производительность.
• Встроенное сильное шифрование.
60.
61.
Где хранятся данныеВсе данные, хранящиеся в Hive, организованы в ящики. Ящик
можно сравнить с таблицей в SQL, но он не имеет структуры и
может содержать что-либо.
Box
LazyBox
Encrypted box
Ящики поддерживают шифрование AES-256 и сжатие (Compaction)
из коробки
62.
Когда использовать• Профили пользователей
• Информация о сеансе
• Комментарии к статье/блогу
• Сообщения
• Содержимое корзины покупок
• Категории товаров
• Двоичные данные
• и т.д.
63.
Когда не использоватьПри правильном моделировании в Hive можно хранить любые
данные. При этом иногда может оказаться удобнее использовать
реляционную базу данных, такую как SQLite. (Удобнее, но не
быстрее!)
Особенно, если ваши данные имеют сложные взаимосвязи и вы в
значительной степени полагаетесь на индексы и сложные запросы,
вам следует рассмотреть возможность использования SQLite.
64.
Ограничения• Ключи должны быть 32-разрядными целыми числами без знака или
строками ASCII с максимальной длиной 255 символов.
• Поддерживаемые целочисленные значения включают все целые числа
в диапазоне от -2^53 до 2^53 и некоторые целые числа с большей
величиной
• Объектам запрещено содержать циклы. Hive не обнаружит их, и
сохранение приведет к бесконечному циклу.
• Только один процесс может получить доступ к коробке в любое время.
В противном случае могут возникнуть проблемы.
• Блоки хранятся в виде файлов в каталоге приложения пользователя.
Поэтому следует избегать распространенных недопустимых символов,
таких как /%&.
65.
• var box = Hive.box('myBox');• await box.put('hello', 'world');
• await box.close();
Вполне нормально оставить box открытым на время
работы приложения. Если вам снова понадобится box в
будущем, просто оставьте его открытым.
66.
Read & Writevar box = Hive.box('myBox');
String name = box.get('name');
DateTime birthday = box.get('birthday');
double height = box.get('randomKey', defaultValue: 17.5);
box.put('name', 'Paul');
box.put('friends', ['Dave', 'Simon', 'Lisa']);
box.put(123, 'test');
box.putAll({'key1': 'value1', 42: 'life'});
67.
Primitive typesHive поддерживает все примитивные типы, List,
Map, DateTime и Uint8List. Если вы хотите сохранить
другие объекты, вам необходимо зарегистрировать
TypeAdapter, который преобразует объект из
двоичной формы и обратно.
68.
class User {String name;
class UserAdapter extends TypeAdapter<User> {
@override
final typeId = 0;
User(this.name);
@override
User read(BinaryReader reader) {
return User(reader.read());
}
@override
String toString() => name; // Just
for print()
}
@override
void write(BinaryWriter writer, User obj) {
writer.write(obj.name);
}
Hive.registerAdapter(UserAdapter());
}
var box = await Hive.openBox<User>('userBox');
box.put('david', User('David'));
box.put('sandy', User('Sandy'));
print(box.values);
69.
Relationshipsclass Person extends HiveObject {
String name;
int age;
List<Person> friends;
Person(this.name, this.age);
}
70.
BoxCollectionsfinal collection = await BoxCollection.open(
'MyFirstFluffyBox',
{'cats', 'dogs'}, // Names of your boxes
path: './', // Path where to store your boxes (Only used in Flutter /
Dart IO)
key: HiveCipher(), // Key to encrypt your boxes (Only used in Flutter /
Dart IO)
);
71.
final catsBox = collection.openBox<Map>('cats');await catsBox.put('fluffy', {'name': 'Fluffy', 'age': 4});
final loki = await catsBox.get('loki');
print('Loki is ${loki?['age']} years old.');
72.
final cats = await catsBox.getAll(['loki', 'fluffy']);print(cats);
final allCatKeys = await catsBox.getAllKeys();
print(allCatKeys);
final catMap = await catsBox.getAllValues();
print(catMap);
await catsBox.delete('loki');
await catsBox.deleteAll(['loki', 'fluffy']);
await catsBox.clear();
73.
await collection.transaction(() async {
await catsBox.put('fluffy', {'name': 'Fluffy', 'age': 4});
await catsBox.put('loki', {'name': 'Loki', 'age': 2});
// ...
},
boxNames: ['cats'], // By default all boxes become blocked.
readOnly: false,
);
74.
Compactionvar box = Hive.box('myBox');
await box.compact();
await box.close();
Вы можете задать свои собственные правила для автоматического
уплотнения. Просто укажите параметр compactionStrategy при
открытии окна:
var box = await Hive.openBox('myBox', compactionStrategy: (entries,
deletedEntries) {
return deletedEntries > 50;
});
75.
Generate adapterimport 'package:hive/hive.dart';
part 'person.g.dart';
@HiveType(typeId: 1)
class Person {
@HiveField(0)
String name;
@HiveField(1)
int age;
@HiveField(2)
List<Person> friends;
}
76.
Updating a classЕсли необходимо изменить существующий класс – например, вы хотите,
чтобы у класса было новое поле, – но вам все равно хотелось бы читать
объекты, написанные с помощью старого адаптера.
Обновить сгенерированные адаптеры просто, не нарушая существующий
код. Просто запомните следующие правила: Не меняйте номера
существующих полей. Если вы добавите новые поля, любые объекты,
записанные "старым" адаптером, все равно будут прочитаны новым
адаптером. Эти поля просто игнорируются. Аналогично, объекты,
написанные вашим новым кодом, могут быть прочитаны вашим старым
кодом: новое поле игнорируется при синтаксическом анализе. Поля могут
быть переименованы и даже изменены с общедоступных…
77.
Encrypted boxfinal appDocumentDir = await getApplicationDocumentsDirectory();
Hive.initFlutter(appDocumentDir.path);
// Initialize encryption
final key = encrypt.Key.fromUtf8('my 32 length super secret key................');
final iv = encrypt.IV.fromLength(16);
final encrypter = encrypt.Encrypter(encrypt.AES(key));
// Open an encrypted box
final encryptedBox = await Hive.openBox('myEncryptedBox',
encryptionCipher: encrypter);
78.
PostgreSql and FlutterПрежде чем углубляться в технические аспекты, важно
понять, почему интеграция PostgreSQL в приложение Flutter может
быть выгодной. Базы данных PostgreSQL предоставляют больше
возможностей для хранения и извлечения сложных данных и
хорошо подходят для серверных приложений, которым требуются
надежные возможности управления данными. С другой стороны,
Flutter отлично справляется с созданием красивых и отзывчивых
пользовательских интерфейсов. Комбинируя эти два компонента,
разработчики
могут
создавать
мощные,
визуально
привлекательные и богатые данными приложения.
79.
Create a User with PermissionsCREATE USER my_flutter_user WITH ENCRYPTED PASSWORD
'my_secure_password';
GRANT ALL PRIVILEGES ON DATABASE my_flutter_app TO
my_flutter_user;
80.
Add PostgreSQL Package Dependencydependencies:
flutter:
sdk: flutter
postgres: ^latest_version
81.
Установление соединения с серверомPostgreSQL
final connection = PostgreSQLConnection(
'host', // Replace with your database host
port, // Replace with your database port
'database_name', // Replace with your database name
username: 'username', // Replace with your username
password: 'password', // Replace with your password
);
await connection.open();
82.
Executing SQL Queries in Dart Codevar result = await connection.query(
'INSERT INTO users(name, email) VALUES (@name, @email)',
substitutionValues: {
'name': 'John Doe',
'email': 'john.doe@example.com'
}
);
83.
Execute a Select QueryList<List<dynamic>> results = await connection.query(
'SELECT * FROM users WHERE name = @name',
substitutionValues: {
'name': 'John Doe'
}
);
for (final row in results) {
print('Name: ${row[0]}, Email: ${row[1]}');
}
84.
Handling Errors and Exceptionstry {
await connection.open();
// Execute queries...
} on PostgreSQLException catch (e) {
print('Error: ${e.toString()}');
} finally {
await connection.close();
}
85.
Future<void> addUser(String name, String email) async {try {
await connection.open();
await connection.query(
'INSERT INTO users(name, email) VALUES (@name, @email)',
substitutionValues: {
'name': name,
'email': email
}
);
} catch (e) {
print('Error: ${e.toString()}');
} finally {
await connection.close();
}
}
86.
Извлечение данных с помощью запросовFuture<List<User>> getUsers() async {
List<User> users = [];
try {
await connection.open();
List<List<dynamic>> results = await connection.query('SELECT * FROM users');
for (var row in results) {
User user = User(name: row[0], email: row[1]);
users.add(user);
}
} catch (e) {
print('Error: ${e.toString()}');
} finally {
await connection.close();
}
return users;}
87.
Обновление данных в базе данныхFuture<void> updateUserEmail(String name, String newEmail) async {
try {
await connection.open();
await connection.query(
'UPDATE users SET email = @newEmail WHERE name = @name',
substitutionValues: {
'name': name,
'newEmail': newEmail
} );
} catch (e) {
print('Error: ${e.toString()}');
} finally {
await connection.close();
}}
88.
Удаление данных из базы данныхFuture<void> deleteUser(String name) async {
try {
await connection.open();
await connection.query(
'DELETE FROM users WHERE name = @name',
substitutionValues: {
'name': name
}
);
} catch (e) {
print('Error: ${e.toString()}');
} finally {
await connection.close();
}
}
89.
Пример транзакцииFuture<void> transferFunds(int fromUserId, int toUserId, double amount) async {
await connection.transaction((ctx) async {
await ctx.query(
'UPDATE accounts SET balance = balance - @amount WHERE user_id = @fromUserId',
substitutionValues: {
'fromUserId': fromUserId,
'amount': amount
});
await ctx.query(
'UPDATE accounts SET balance = balance + @amount WHERE user_id = @toUserId',
substitutionValues: {
'toUserId': toUserId,
'amount': amount } ); });}
90.
Выводы по Postgres in FlutterРабота с PostgreSQL в проекте Flutter требует понимания того,
как устанавливать соединение, выполнять запросы и управлять
данными. Вы можете эффективно интегрировать базу данных
PostgreSQL в свои приложения Flutter, используя пакет “Postgres” и
шаблон асинхронного ожидания Dart.
informatics