👻
【Flutter × Realm】サービスクラスやコントローラーを使って汎用的にRealmを使う
初めに/概要
flutterでRealmを汎用的に使用する方法を紹介します。
結論としては、realm専用のサービスクラスを作り、各コントローラーでサービスクラスの関数を呼び出す、ということをしています。
realm以外でも使える方法ですので、参考にしてもらえれば嬉しいです!
対象
flutterにて、realmを汎用的に使ってみたい方
目標
- realm用のServiceクラスで使って、他ファイルからrealmのDBにデータを作成や取得できるようになる
実装
realmの導入・Modelファイルを作成
こちらは、前回の記事を参考に進めてください!
realm用のサービスクラスを導入
汎用的にrealmを使用可能にするためにサービスクラスを作成します。
realm.service.dartファイルを新規作成し、以下のように実装します。
initialize関数を呼ぶことでrealmを使用可能にするためにrealmのインスタンス化をします。
realm.service.dart
import 'package:realm/realm.dart';
class RealmService {
static RealmService realmInstance = RealmService(); // サービスクラスのインスタンス化
late Realm realm;
final config = Configuration.local([Member.schema, Department.schema]); //作成したschemaをconfig内に設定
// realmを使用可能にするために初期化(realmのインスタンス化)します。
void initialize() {
realm = Realm(config);
}
}
realmをインスタンス化する
MyApp()を呼び出すタイミング(=main関数内で呼ばれる)でrealmのインスタンス化を行います。
main.dart
class MyApp extends StatelessWidget {
MyApp({super.key}) {
RealmService.realmInstance.initialize();
}
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
realmを汎用的に使ってみる
Realmサービス内でRealmでCRUDする処理を追加する
今回はCreatとReadの処理を実装します。
realm.service.dart
import './schema.dart';
import 'package:realm/realm.dart';
class RealmService {
static RealmService realmInstance = RealmService();
late Realm realm;
final config = Configuration.local([Member.schema, Department.schema]);
// CREATE: realmのMemberテーブルにmemberを追加する処理
void addMember(Member member) {
realm.write(() => realm.add(member));
}
// READ: realmのMemberテーブルを参照する処理
List<Member> getMembers(String query) => realm.all<Member>().query(query).toList();
void initialize() {
realm = Realm(config);
print('realmPath: ${config.path}');
}
}
ページ用のコントローラーを用意
ビジネスロジックはコントローラーで行いたいため、realmを使用するロジックはコントローラーで書きます。
import './schema.dart';
import './realm.dart';
import 'package:realm/realm.dart';
class MainController {
void getDepartments() {
final departments = RealmService.realmInstance.getDepartments('TRUEPREDICATE SORT(id ASC)');
print('department一覧: $departments');
}
// realmサービスのgetMembers(Read処理)関数を実行
void getMembers() {
final members =
RealmService.realmInstance.getMembers('TRUEPREDICATE SORT(id ASC)');
print('全member数: ${members.length}');
}
// realmサービスのaddMember(Creat処理)関数を実行
void addMember(int counterNum) {
final member = Member(
ObjectId(),
'Hana Kojima$counterNum',
'hana.kojima$counterNum@sample.com',
);
RealmService.realmInstance.addMember(member);
// realmに追加されたかを確認するために、Memberテーブルを参照
final members =
RealmService.realmInstance.getMembers('TRUEPREDICATE SORT(id ASC)');
print('追加後: 全member数: ${members.length}');
for (var member in members) {
print(member.name);
}
}
// MainController内の処理を使用可能にするためにインスタンス化
MainController();
}
ページ用のコントローラーを用意
ビジネスロジックを記載したコントローラーをページで扱えるようにし、処理の実行をします。
floatingActionButtonを押下することで、コントローラーのaddMember関数を実行させます。
main.dart
import 'package:flutter/material.dart';
import './main.controller.dart';
import './realm.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
MyApp({super.key}) {
RealmService.realmInstance.initialize();
}
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// MainControllerをインスタンス化
final MainController mainController = MainController();
int _counter = 0;
@override
void initState() {
// MainController内のgetMembers関数を実行
mainController.getMembers();
super.initState();
}
// MainController内のaddMember関数を実行
void _addMember() {
setState(() {
_counter++;
});
mainController.addMember(_counter);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Realm sample'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _addMember,
tooltip: 'AddMember',
child: const Icon(Icons.add),
),
);
}
}
最後に
このように、realmをどこでも使用可能にする実装を紹介しました。
realm以外でもサービスクラスやコントローラーを用意することで、汎用的にわかりやすく実装することが可能です。
以上で終了です。お疲れ様でした!
参考になった方は、ぜひ、いいねをいただけると嬉しいです!
サンプルコードとして、githubのソースコードを共有します。
Discussion