Flutter SQLite FFI с использованием болота
Цель этого поста — продемонстрировать «Как использовать SQLite FFI с библиотекой moor?».
Flutter Mobile может использовать дартс:библиотека ffi для вызова собственных API-интерфейсов C. FFI означает внешний функциональный интерфейс. Другие термины для аналогичной функциональности включают собственный интерфейс и языковые привязки.
Проще говоря, нам не нужен какой-либо канал метода для вызова собственного API Android/IOS. Мы можем напрямую получить доступ к тем, кто находится в дротике, с помощью ffi.
Шаг: 1 Добавьте зависимости в pubspec
Добавьте следующие зависимости в свой pubspec.yaml.
moor: ^2.0.0
moor_ffi: ^0.0.1
provider: ^3.0.0+1
path_provider: ^1.3.0
dev_dependencies:
moor_generator: ^2.0.0
build_runner:
Шаг: 2 создайте простой класс сущности (movie_entity.dart)
import 'package:moor/moor.dart';
class MovieEntity extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text().withLength(min: 1, max: 50)();
}
Шаг: 3 создайте класс базы данных (app_db.dart)
import 'dart:io';
import 'package:moor/moor.dart';
import 'package:moor_ffi/moor_ffi.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
import 'movie_entity.dart';
part 'app_db.g.dart';
@UseMoor(tables: [MovieEntity])
class AppDatabase extends _$AppDatabase {
AppDatabase()
: super(
LazyDatabase(() async {
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'myDB.sqlite'));
return VmDatabase(file);
}),
);
@override
int get schemaVersion => 1;
// This two methods can be extracted in DAO.
Future insertMovie(MovieEntityData movie) => into(movieEntity).insert(movie);
Stream<List<MovieEntityData>> watchAllMovies() => select(movieEntity).watch();
}
Давайте запустим BuildRunner для генерации кода.flutter pub run build_runner build
Как только мы сгенерируем код, мы увидим MovieEntityData как DataClass и movieEntity как Table.
Шаг: 4 Давайте создадим пользовательский интерфейс (home_page.dart)
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sql_ffi/app_db.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
final AppDatabase appDatabase = Provider.of<AppDatabase>(context);
return Scaffold(
appBar: AppBar(
title: Text('SQL FFI Demo'),
),
body: Column(
children: <Widget>[
StreamBuilder(
stream: appDatabase.watchAllMovies(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
List<MovieEntityData> users = snapshot.data;
if (users.isNotEmpty) {
return Expanded(
flex: 5,
child: ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: users.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(users[index].name),
);
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
),
);
}
}
return const SizedBox(height: 10);
},
),
const SizedBox(height: 20),
Container(
padding: const EdgeInsets.all(10.0),
color: Colors.grey[200],
child: Align(
alignment: Alignment.bottomCenter,
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: 'Enter movie name',
),
controller: _controller,
),
RaisedButton(
child: const Text('Save Movie'),
onPressed: () async {
final movieName = _controller.text;
if (movieName.isNotEmpty) {
int id = Random().nextInt(100);
MovieEntityData movieEntity =
MovieEntityData(id: id, name: '$movieName');
await appDatabase.insertMovie(movieEntity);
_controller.clear();
}
},
),
],
),
),
),
const SizedBox(height: 20),
],
),
);
}
}
Шаг:5 Давайте создадим пользовательский интерфейс (main.dart)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'app_db.dart';
import 'home_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Provider(
builder: (_) => AppDatabase(),
child: MaterialApp(
title: 'Material App',
home: HomePage(),
),
);
}
}
Вот и наслаждайся