Flutter開発入門 ObjectBoxでデータ管理

Flutter

はじめに

 本記事ではFlutterのObjectBoxの利用方法とサンプルを記載します。VSCodeを用いて実施するので環境構築が住んでいない方は以下をご覧ください

 ObjectBoxは、高速なトランザクションを実現するために特化したモバイルとIoT向けの軽量データベースです。他のデータベースライブラリと比較して、ObjectBoxの主な利点は以下の通りです。
 また、2024年8月時点で更新されているので、オープンソース上の開発も盛んに行われています。

  • 高速性: ObjectBoxは読み書きの速度が非常に速く、大量のデータ操作でも効率的に処理します。
  • リソース効率: 非常に少ないメモリとストレージを使用し、リソースが限られたデバイスでも高いパフォーマンスを発揮します。
  • 開発の容易さ: ObjectBoxのAPIはシンプルで直感的なため、開発者は短時間でデータベース操作を学び、適用することが可能です。

これらの特性により、ObjectBoxはモバイルデバイスやIoTデバイスに最適な選択肢となっています。

2. 環境設定

  では実際にFlutterプロジェクトを作成するところから始めていきます。プロジェクト名は「objectbox_sample」としました。

  1. Flutterプロジェクトの作成:
    • Visual Studio Codeを開き、コマンドパレット (Ctrl+Shift+P / Cmd+Shift+P) を使用して「Flutter: New Project」と入力します。
    • プロジェクトの種類を選択し、プロジェクト名と保存先を指定してプロジェクトを作成します。
  2. ObjectBox Flutterの依存関係を追加:
    • pubspec.yaml ファイルを開き、dependenciesセクションにobjectbox_flutter_libs、objectbox、objectbox_generator、build_runnerを追加します。
dependencies:
  flutter:
    sdk: flutter

  objectbox: ^4.0.2 #ここを追加
  objectbox_flutter_libs: any #ここを追加

dev_dependencies:
  flutter_test:
    sdk: flutter

  objectbox_generator: any  #ここを追加
  build_runner: ^2.4.12 #ここを追加
  1. パッケージのインストール:
    • 以下コマンドを叩いてパッケージをインストールします。
flutter pub get

3. モデルの定義

 ここでは簡単なモデルを作成します。user.dartを作成して以下を記述します。
ポイントとしては@Entity()でエンティティの定義をしていることと、idは必須になるので定義しています。

import 'package:objectbox/objectbox.dart';

@Entity()
class User {
  int id = 0; // ObjectBoxはデフォルトでidを必要とします。

  String name;
  int age;

  User({this.id = 0, required this.name, required this.age});
}

 次にObjectBoxを実行するために以下コマンドを実行します。

flutter pub run build_runner build

 実行すると、objectbox-model.jsonとobjectbox.g.dartが生成されたことを確認してください。

4. ObjectBoxの初期化

 ObjectBoxを初期化します。少し長いのでmain.dartをそのまま記載します。

import 'package:flutter/material.dart';
import 'package:objectbox/objectbox.dart';
import 'package:objectbox_sample/objectbox.g.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';

late final ObjectBox box;
void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // ObjectBoxの初期化
  box = await ObjectBox.create();

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      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.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class ObjectBox {
  late final Store store;

  ObjectBox._create(this.store) {}

  static Future<ObjectBox> create() async {
    final docsDir = await getApplicationDocumentsDirectory();
    final store = await openStore(directory: p.join(docsDir.path, "obx-store"));
    return ObjectBox._create(store);
  }
}

5. データベースの操作

 次にObjectBoxを使ってデータベースを操作してみます。今回はシンプルなCRUD処理を作成しました。

// データの挿入
  void insertUser(User user) {
    final userBox = box.store.box<User>();
    userBox.put(user);
  }

// データの読み出し
  User? getUser(int id) {
    final userBox = box.store.box<User>();
    return userBox.get(id);
  }

// データの更新
  void updateUser(User user) {
    final userBox = box.store.box<User>();
    user.name = 'Updated Name'; // 名前を更新
    userBox.put(user);
  }

// データの削除
  void deleteUser(int id) {
    final userBox = box.store.box<User>();
    userBox.remove(id);
  }

 以上がObjectBoxの環境作成から操作までのコードになります。

6. パフォーマンスと最適化

 ObjectBoxを利用する上で簡単にパフォーマンスの最適化のヒントを記載します。実際のコードはプロジェクトの特性などを加味して設計してください。※一般的なDB技術と重複します。

  1. インデックスの適用: 頻繁にアクセスする属性にインデックスを適用することで、検索速度が大幅に向上します。例えば、ユーザー名やIDのような属性にインデックスを設定すると効果的です。
  2. 関連データの効率的な管理: エンティティ間の関係を適切に設計することで、データベースの構造を単純化し、関連データの取得コストを削減します。
  3. 非同期処理の活用: ObjectBoxは非同期APIを提供しており、これを利用することで、重いデータ操作がアプリケーションの応答性を阻害することなくバックグラウンドで実行されます。
  4. トランザクションの最適化: ObjectBoxでは、複数の書き込み操作を一つのトランザクションでまとめて実行することで、オーバーヘッドを減らし、効率を向上させることができます。

8. まとめ

 この記事では、Visual Studio Code (VSCode) を使って Flutter アプリケーションに ObjectBox データベースを統合する方法について詳しく説明しました。環境設定から始め、モデルの定義、データベースの初期化、CRUD操作までのステップバイステップのプロセスを解説し、パフォーマンスの最適化についても触れました。是非ObjectBoxを使ってみてください。

コメント