【Flutter】hiveの後継Isarを試してみる
isar | Dart Package
hiveのv2系として別プロジェクトで進められている、isarを実際にアプリに組み込んで使う想定で色々試してみたいと思います。
環境セットアップ
pubspec.yaml
に以下を追加
dependencies:
isar: 2.2.1
isar_flutter_libs: 2.2.1 # contains the binaries
dev_dependencies:
isar_generator: 2.2.1
build_runner: any
user
テーブルを作成してみる
試しに import 'package:isar/isar.dart';
part 'user.g.dart';
()
class User {
()
int? id;
late String name;
String? avatarUri;
late DateTime createdAt;
late DateTime updatedAt;
}
build_runner
実行
$ flutter pub run build_runner build
user.g.dart
が生成されていればOKです。
スプラッシュ画面中にisar初期化を行う想定で試してみる
実際にisar初期化する場面を想定して、今回はスプラッシュ画面表示中に初期化を実施してみたいと思います。
まずは、flutter_native_splash と path_provider パッケージを追加します。
dependencies:
flutter_native_splash: ^2.1.6
path_provider: ^2.0.9
適当なアイコン用意して pubspec.yaml
に以下を追加します。
flutter_native_splash:
color: '#ffffff'
image: 'assets/images/splash.png'
fullscreen: true
※ 今回はAndroid12対応など細かい所は省略してます
flutter pub run flutter_native_splash:create
コマンド実施してsplash画面を作成。
ver 2.0.3以降から FlutterNativeSplash.remove()
呼ぶまでsplash画面を表示してくれるみたいなので、そちらを使ってisarの初期化を実装してみたいと思います。
import 'package:flutter_native_splash/flutter_native_splash.dart';
void main() {
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
runApp(const MyApp());
}
MyApp
内で初期化 + スプラッシュ画面を非表示にする処理を追加します。
import 'package:isar/isar.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
late Isar isar;
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Future<void> initialize() async {
final dir = await getApplicationSupportDirectory();
isar = await Isar.open(
schemas: [UserSchema],
directory: dir.path,
inspector: true);
FlutterNativeSplash.remove(); // ← スプラッシュを非表示にする
}
Widget build(BuildContext context) {
return FutureBuilder(
future: initialize(),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
});
}
}
これでスプラッシュ画面後には isar
が使える状態になっています。
Riverpodと組み合わせて使ってみる
実際にありそうな Riverpod と組み合わせて使う想定で進めていきたいと思います。
今回は実際にisarを使用する user_service.dart
と利用する user_repository.dart
を作成します。
- user_service.dart
- Riverpodのfamilyを使用して、外部からisarのインスタンスをDIできる様にしてます
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:isar/isar.dart';
import 'package:xxxx/repositories/entities/user.dart';
final ProviderFamily<UserService, Isar> userServiceProvider =
Provider.family<UserService, Isar>((_, isar) => UserService(isar: isar));
class UserService {
UserService({required this.isar});
final Isar isar;
Future<User?> find() async {
return isar.users.where().findFirst(); // 1ユーザーしか登録しない想定
}
Future<int> add({required String name, String? avatarUri}) async {
final user = User()
..name = name
..avatarUri = avatarUri
..createdAt = DateTime.now()
..updatedAt = DateTime.now();
return isar.writeTxn((isar) => isar.users.put(user));
}
}
- user_repository.dart
- user_serviceに渡すisarはスプラッシュ画面中に初期化したものを渡しています
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:xxxx/app.dart';
import 'package:xxxx/repositories/entities/user.dart';
import 'package:xxxx/repositories/services/db/user_service.dart';
final Provider<UserRepository> userRepositoryProvider =
Provider<UserRepository>(
(ref) => UserRepository(service: ref.watch(userServiceProvider(isar))));
class UserRepository {
UserRepository({required this.service});
final UserService service;
Future<User?> find() => service.find();
// ユーザー未登録の場合ユーザー作成
Future<void> initUser() async {
final user = await find();
if (user == null) {
await service.add(name: 'anonymous');
}
}
}
あとは ref.watch(userRepositoryProvider)
で使って進めていけば良さそうかと思います。
Isar Inspector を使ってみる
isar/README.md at main · isar/isar
実際のデータを参照できる Isar Inspectorを使ってみたいと思います。
まずは リリースページから Isar.Inspector.zip
をダウンロードしてきます。
Isar.open
する際に inspector: true
のパラメータが必要との事なので inspector: true
を追加し起動するとコンソールに
以下の様なメッセージが表示されるようになります。
指定されたURLを Isar Inspectorに設定してやると見れるようになります。
↓ Isar Inspectorを起動した様子
バッドノウハウ
build_runner
実行時に以下のエラーが発生する。
line 1, column 22 of package:xxxx/user.dart: Could not resolve annotation for `class User`.
╷
1 │ @Collection()
│ ^^^^^^^^^^^^^
╵
公式のサンプルには無い import 'package:isar/isar.dart';
を先頭に追記
Discussion