flutter_lmdb2 0.9.5
flutter_lmdb2: ^0.9.5 copied to clipboard
Flutter plugin to include native LMDB (Lightning Memory-Mapped Database), providing both high-level convenience methods and low-level transaction control.
import 'dart:ffi';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_lmdb2/lmdb.dart';
import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(const FlutterLMDBDemo());
}
class FlutterLMDBDemo extends StatelessWidget {
const FlutterLMDBDemo({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo with flutter_lmdb2',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _status = 'Initializing...';
late LMDB _db;
var logger = Logger(
printer: SimplePrinter(colors: true, printTime: true),
);
@override
void initState() {
super.initState();
_initDatabase();
}
Future<void> _initDatabase() async {
try {
logger.d('Starting database initialization...');
final appDir = await getApplicationDocumentsDirectory();
final dbPath = '${appDir.path}/lmdb_test';
logger.d('Using database path: $dbPath');
// Ensure directory exists
final dbDir = Directory(dbPath);
if (!dbDir.existsSync()) {
try {
dbDir.createSync(recursive: true);
logger.d('Created database directory: $dbPath');
} catch (e) {
logger.e('Failed to create directory: $e');
setState(() {
_status = 'Failed to create database directory: $e';
});
return;
}
}
// Check directory permissions
await checkDirectoryPermissions(dbPath);
// Initialize database
_db = LMDB();
logger.d('Created LMDB instance');
try {
var flags = LMDBFlagSet();
if (Platform.isMacOS) {
// Sandbox restrictions apply
flags.add(MDB_NOLOCK);
}
await _db.init(dbPath,
config: LMDBInitConfig(mapSize: 10 * 1024 * 1024), flags: flags);
logger.d('Database initialized successfully');
} catch (e) {
logger.e('Database initialization failed: $e');
setState(() {
_status = 'Database initialization failed: $e';
});
return;
}
// Test write with error handling
late final Pointer<MDB_txn> txn;
try {
txn = await _db.txnStart();
logger.d('Transaction started');
} catch (e) {
logger.e('Failed to start transaction: $e');
setState(() {
_status = 'Failed to start transaction: $e';
});
return;
}
try {
await _db.putUtf8(txn, 'greeting', 'Hello from LMDB!');
logger.d('Data written');
await _db.txnCommit(txn);
logger.d('Transaction committed');
} catch (e) {
logger.e('Write operation failed: $e');
try {
await _db.txnAbort(txn);
} catch (abortError) {
logger.e('Additionally, transaction abort failed: $abortError');
}
setState(() {
_status = 'Write operation failed: $e';
});
return;
}
// Test read with error handling
late final Pointer<MDB_txn> readTxn;
try {
readTxn = await _db.txnStart();
} catch (e) {
logger.e('Failed to start read transaction: $e');
setState(() {
_status = 'Failed to start read transaction: $e';
});
return;
}
try {
final value = await _db.getUtf8(readTxn, 'greeting');
logger.d('Data read: $value');
await _db.txnCommit(readTxn);
setState(() {
_status = 'DB Test successful!\nRead value: $value';
});
} catch (e) {
logger.e('Read operation failed: $e');
try {
await _db.txnAbort(readTxn);
} catch (abortError) {
logger.e('Additionally, read transaction abort failed: $abortError');
}
setState(() {
_status = 'Read operation failed: $e';
});
}
} catch (e) {
logger.e('Unexpected error during database operations: $e');
setState(() {
_status = 'Unexpected error: $e';
});
}
}
Future<void> checkDirectoryPermissions(String dbPath) async {
try {
final file = File('$dbPath/test.txt');
await file.writeAsString('test');
await file.delete();
logger.d('Directory permissions verified');
} catch (e) {
logger.e('Directory permission test failed: $e');
setState(() {
_status = 'No write permission in database directory: $e';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('flutter_lmdb2 Flutter Demo'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Database Status:',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 16),
Text(
_status,
style: Theme.of(context).textTheme.bodyLarge,
textAlign: TextAlign.center,
),
],
),
),
),
);
}
@override
void dispose() {
try {
_db.close();
logger.d('Database closed successfully');
} catch (e) {
logger.e('Error closing database: $e');
}
super.dispose();
}
}