Docs Menu
Docs Home
/ /
Atlas App Services

チュートリアル: Atlas Device Sync for Flutter

項目一覧

  • 学習目的
  • 前提条件
  • テンプレートを使用して開始
  • テンプレート アプリの設定
  • アプリを開く
  • アプリ構造の探索
  • アプリを実行する
  • バックエンドの確認
  • アプリケーションを変更する
  • 新しいプロパティの追加
  • モデルへの新しいプロパティの追加
  • アイテムの作成および更新時の優先順位の設定
  • およびテストの実行
  • サブスクリプションを変更する
  • サブスクライブを更新する
  • およびテストの実行
  • まとめ
  • 次のステップ

完了までの推定時間:30分(Flutter の経験により異なります)

Atlas Device SDK for Flutter を使用すると、Dart と Flutter を使用してマルチプラットフォーム アプリケーションを作成できます。 このチュートリアルは、Todo アプリケーションの作成を説明する、 flutter.todo.flexという名前の Flutter Flexible Sync テンプレート アプリに基づいています。 このアプリケーションを使用すると、ユーザーは次のことが可能になります。

  • メールを新しいユーザー アカウントとして登録します。

  • メールとパスワードを使用してアカウントにサインインします(その後サインアウトします)。

  • タスク アイテムを表示、作成、変更、および削除します。

  • ユーザーが所有者でない場合でも、すべてのタスクを表示します。

また、テンプレートアプリには、デバイスがオフラインモードになっていることをシミュレートするトグルが用意されています。このトグルを使用すると、Device Sync 機能をすばやくテストして、インターネットに接続していないユーザーをエミュレートできます。ただし、本番アプリケーションではこのトグルを削除する可能性が高いでしょう。

このチュートリアルは、テンプレート アプリに追加します。既存のItem モデルに新しい priority フィールドを追加し、Flexible Sync サブスクリプションを更新して、優先順位の範囲内のアイテムのみを表示します。

このチュートリアルでは、テンプレート アプリを独自のニーズに合わせて調整する方法について説明します。 テンプレート アプリの現在の構造を考慮すると、必ずしもこの変更を行う必要はありません。

このチュートリアルでは、次の方法を学習します。

  • Realm オブジェクトモデルを重大じゃない変更で更新します。

  • Device Sync サブスクリプションを更新する

  • 同期されるデータを変更するには、サーバー上の Device Sync 構成にクエリ可能なフィールドを追加します。

ガイド付きチュートリアルに従うのではなく、独自のアプリケーションを使い始める場合は、 Flutter クイック スタートを確認してください。 コピー可能なコード サンプルと Flutter SDK アプリケーションを設定するために必要な重要な情報が含まれています。

  • Flutter アプリを Android エミュレーター、iOS シミュレーター、物理デバイスにデプロイした経験が必要です。

  • このチュートリアルは、テンプレート アプリから始めます。 テンプレート アプリを作成するには、 Atlas アカウント、 API キー、 App Services CLI が必要です。

    • Atlas アカウントの作成の詳細については、「 Atlas の使用開始」ドキュメントを参照してください。 このチュートリアルでは、無料階層クラスターを持つ Atlas アカウントが必要です。

    • ログインする MongoDB Cloud アカウントの Atlas API キーも必要です。 App Services CLI を使用してテンプレート アプリを作成するには、プロジェクト オーナーである必要があります。

    • App Services CLI のインストールについて詳しくは、「 App Services CLI のインストール」を参照してください。 インストール後、Atlas プロジェクトの API キーを使用して「 login 」コマンドを実行します。

注意

サポートされているプラットフォーム

このチュートリアル アプリは、次のプラットフォームでビルドできます。

  • iOS

  • Android

  • MacOS

  • Windows

  • Linux

Flutter SDK はウェブ アプリケーションのビルドをサポートしていません

このチュートリアルは、flutter.todo.flexという名前の Flutter Flexible Sync テンプレート アプリを基本にして作成されており、デフォルトのアプリから始めて、新しい機能について説明しています。

テンプレート アプリの詳細については、「テンプレート アプリ 」を参照してください。

Atlas アカウントがまだない場合は、テンプレート アプリを配置するためにサインアップしてください。

App Services App」ガイドに記載されている手順に従い、 Create App from Templateを選択します。Real-time Sync テンプレートを選択します。これにより、Device Sync テンプレート App Services App クライアントの 1 つで使用するために事前構成された App Services App が作成されます。

テンプレート アプリを作成すると、UI に Get the Front-end Code for your Template というラベルの付いたモーダルが表示されます。このモーダルには、テンプレート アプリのクライアントコードを .zip ファイルとしてダウンロードする方法や、App Services CLI を使用してクライアントを取得する方法が表示されます。

.zip または App Services CLI メソッドを選択した後、画面の指示に従ってクライアント コードを取得します。このチュートリアルでは、Dart (Flutter) クライアント コードを選択します。

ダウンロードしたアプリを解凍すると、Flutter アプリが表示されます。

注意

デフォルトの Windows ZIP ユーティリティで、.zip ファイルが空白ファイルとして表示される。この問題が発生した場合は、利用可能なサードパーティの zip プログラムのいずれかを使用してください。

appservices apps create コマンドでバックエンドを設定し、Flutter テンプレート アプリを作成してこのチュートリアルのベースとして使用します。

ターミナル ウィンドウで次のコマンドを実行して、「Myチュートリアル App」という名前のアプリを作成し、環境が「開発」(本番環境やQAではなく)に設定されているUS-VAリージョンに配置されます。

appservices app create \
--name MyTutorialApp \
--template flutter.todo.flex \
--deployment-model global \
--environment development

このコマンドは、 --nameフラグの値と同じ名前で現在のパスに新しいディレクトリを作成します。

Device Sync クライアントコードを含む Github リポジトリをフォークしてクローンできます。Flutter クライアントコードは https://github.com/mongodb/template-app-dart-flutter-todo で入手できます。

このプロセスを使用してクライアントのコードを取得する場合は、クライアントで使用するテンプレート アプリを作成する必要があります。「テンプレート アプリの作成」の手順に従って、Atlas App Services UI、App Services CLI、または管理 API を使用して Device Sync バックエンド テンプレート アプリを作成します。

リポジトリをクローンし、README の指示に従ってバックエンド アプリ ID を Flutter アプリに追加します。

1

コード エディターで Flutter アプリを開きます。

クライアントを .zip ファイルとしてダウンロードした場合、またはクライアントGithubリポジトリをクローンした場合は、クライアント内の適切な場所にApp Services App IDを手動で挿入する必要があります。 アプリ ID を挿入する場所については、クライアントREADME.mdConfigurationの手順に従ってください。

2

コードエディターで、少し時間を取って、プロジェクトがどのように構成されているかを調べます。これは、特定の用途に合わせて変更された標準的なマルチプラットフォーム Flutter アプリケーションです。具体的には、次のファイルには Flutter SDK の重要な用途が含まれています。

ファイル
目的
lib/main.dart
アプリへのエントリポイント。ルーティングと状態マネジメントを含みます。
lib/realm/schemas.dart
Realm Database スキーマを定義します。
lib/realm/schemas.realm.dart
生成された Realm オブジェクト クラス。
lib/realm/app_services.dart
Atlas App Services とのやり取りを処理します。
lib/realm/realm_services.dart
Realm Database および Atlas Device Sync とのやり取りを処理します。
lib/components/
Flutter ウィジェットを搭載したアプリのコンポーネント部分。
lib/screens/
アプリのページ。
3

コードを変更しなくても、Android エミュレーター、iOS シミュレーター、物理モバイルデバイス、またはデスクトップ エミュレーターのいずれかでアプリを実行できるはずです。

ターミナルで以下を実行して、すべての依存関係をインストールします。

flutter pub get

デバイスに接続して Flutter アプリケーションを実行します。

アプリを実行したら、新しいユーザーアカウントを登録し、新しいアイテムを Todo リストに追加します。

Tip

開発ツールを使用して Flutter アプリを実行する方法の詳細については、 Flutter Test Drive ドキュメントを参照してください。

4

MongoDB Atlasにログインします。 Data Servicesタブで、 Browse Collectionsをクリックします。 データベースのリストで、 todoデータベース、 Itemコレクションを検索して展開します。 このコレクションで作成したドキュメントが表示されます。

1

すべて期待どおりに動作していることが確認できたため、変更を追加できます。このチュートリアルでは、各アイテムに「優先順位」プロパティを追加し、アイテムに優先順位をつけてフィルタリングできるようにしました。

これを行うには、次の手順に従います。

  1. flutter.todo.flex プロジェクトで、ファイルlib/realm/schemas.dartを開きます。

  2. 次のプロパティを_Itemクラスに追加します。

    lib/realm/schemas.dart
    late int? priority;
  3. Item Realm オブジェクト クラスを再生成します。

    dart run realm generate
2
  1. lib/realm/realm_services.dartに、priorityを設定および更新するロジックを追加します。また、可能な値を制限するために、 RealmServicesクラスの下にPriorityLevel抽象クラスを追加します。

    lib/realm/realm_services.dart
    // ... imports
    class RealmServices with ChangeNotifier {
    static const String queryAllName = "getAllItemsSubscription";
    static const String queryMyItemsName = "getMyItemsSubscription";
    bool showAll = false;
    bool offlineModeOn = false;
    bool isWaiting = false;
    late Realm realm;
    User? currentUser;
    App app;
    // ... RealmServices initializer and updateSubscriptions(),
    // sessionSwitch() and switchSubscription() methods
    void createItem(String summary, bool isComplete, int? priority) {
    final newItem = Item(ObjectId(), summary, currentUser!.id,
    isComplete: isComplete, priority: priority);
    realm.write<Item>(() => realm.add<Item>(newItem));
    notifyListeners();
    }
    void deleteItem(Item item) {
    realm.write(() => realm.delete(item));
    notifyListeners();
    }
    Future<void> updateItem(Item item,
    {String? summary,
    bool? isComplete,
    int? priority}) async {
    realm.write(() {
    if (summary != null) {
    item.summary = summary;
    }
    if (isComplete != null) {
    item.isComplete = isComplete;
    }
    if (priority != null) {
    item.priority = priority;
    }
    });
    notifyListeners();
    }
    Future<void> close() async {
    if (currentUser != null) {
    await currentUser?.logOut();
    currentUser = null;
    }
    realm.close();
    }
    @override
    void dispose() {
    realm.close();
    super.dispose();
    }
    }
    abstract class PriorityLevel {
    static int severe = 0;
    static int high = 1;
    static int medium = 2;
    static int low = 3;
    }
  2. アイテムの優先順位を設定するウィジェットを含む新しいファイルを追加します。ファイルlib/components/select_priority.dartを作成します。

    lib/components/select_priority.dart
    import 'package:flutter/material.dart';
    import 'package:flutter_todo/realm/realm_services.dart';
    class SelectPriority extends StatefulWidget {
    int priority;
    void Function(int priority) setFormPriority;
    SelectPriority(this.priority, this.setFormPriority, {Key? key})
    : super(key: key);
    @override
    State<SelectPriority> createState() => _SelectPriorityState();
    }
    class _SelectPriorityState extends State<SelectPriority> {
    @override
    Widget build(BuildContext context) {
    return Padding(
    padding: const EdgeInsets.only(top: 15),
    child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    const Text('Priority'),
    DropdownButtonFormField<int>(
    onChanged: ((int? value) {
    final valueOrDefault = value ?? PriorityLevel.low;
    widget.setFormPriority(valueOrDefault);
    setState(() {
    widget.priority = valueOrDefault;
    });
    }),
    value: widget.priority,
    items: [
    DropdownMenuItem(
    value: PriorityLevel.low, child: const Text("Low")),
    DropdownMenuItem(
    value: PriorityLevel.medium, child: const Text("Medium")),
    DropdownMenuItem(
    value: PriorityLevel.high, child: const Text("High")),
    DropdownMenuItem(
    value: PriorityLevel.severe, child: const Text("Severe")),
    ],
    ),
    ],
    ),
    );
    }
    }
  3. ここで、SelectPriorityウィジェットをCreateItemウィジェットとModifyItemウィジェットに追加します。優先順位の設定を処理するための追加ロジックも追加する必要があります。追加する必要があるコードを以下に示します。

    以下のコード例では、追加先のファイルの一部のセクションがコメントに置き換えられ、変更されたコードの関連セクションに焦点が当てられています。

    lib/components/create_item.dartCreateItemFormウィジェットを編集します。

    lib/components/create_item.dart
    // ... other imports
    import 'package:flutter_todo/components/select_priority.dart';
    // ... CreateItemAction widget
    class CreateItemForm extends StatefulWidget {
    const CreateItemForm({Key? key}) : super(key: key);
    @override
    createState() => _CreateItemFormState();
    }
    class _CreateItemFormState extends State<CreateItemForm> {
    final _formKey = GlobalKey<FormState>();
    late TextEditingController _itemEditingController;
    int _priority = PriorityLevel.low;
    void _setPriority(int priority) {
    setState(() {
    _priority = priority;
    });
    }
    // ... initState() and dispose() @override functions
    @override
    Widget build(BuildContext context) {
    TextTheme theme = Theme.of(context).textTheme;
    return formLayout(
    context,
    Form(
    key: _formKey,
    child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
    // ... Text and TextFormField widgets
    SelectPriority(_priority, _setPriority),
    // ... Padding widget
    ],
    ),
    ));
    }
    void save(RealmServices realmServices, BuildContext context) {
    if (_formKey.currentState!.validate()) {
    final summary = _itemEditingController.text;
    realmServices.createItem(summary, false, _priority);
    Navigator.pop(context);
    }
    }
    }

    lib/components/modify_item.dartModifyItemFormウィジェットを編集します。

    lib/components/modify_item.dart
    // ... other imports
    import 'package:flutter_todo/components/select_priority.dart';
    class ModifyItemForm extends StatefulWidget {
    final Item item;
    const ModifyItemForm(this.item, {Key? key}) : super(key: key);
    @override
    _ModifyItemFormState createState() => _ModifyItemFormState(item);
    }
    class _ModifyItemFormState extends State<ModifyItemForm> {
    final _formKey = GlobalKey<FormState>();
    final Item item;
    late TextEditingController _summaryController;
    late ValueNotifier<bool> _isCompleteController;
    late int? _priority;
    void _setPriority(int priority) {
    setState(() {
    _priority = priority;
    });
    }
    _ModifyItemFormState(this.item);
    @override
    void initState() {
    _summaryController = TextEditingController(text: item.summary);
    _isCompleteController = ValueNotifier<bool>(item.isComplete)
    ..addListener(() => setState(() {}));
    _priority = widget.item.priority;
    super.initState();
    }
    @override
    void dispose() {
    _summaryController.dispose();
    _isCompleteController.dispose();
    super.dispose();
    }
    @override
    Widget build(BuildContext context) {
    TextTheme myTextTheme = Theme.of(context).textTheme;
    final realmServices = Provider.of<RealmServices>(context, listen: false);
    return formLayout(
    context,
    Form(
    key: _formKey,
    child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
    // ... Text and TextFormField widgets
    SelectPriority(_priority ?? PriorityLevel.medium, _setPriority),
    // ... StatefulBuilder widget
    Padding(
    padding: const EdgeInsets.only(top: 15),
    child: Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
    cancelButton(context),
    deleteButton(context,
    onPressed: () =>
    delete(realmServices, item, context)),
    okButton(context, "Update",
    onPressed: () async => await update(
    context,
    realmServices,
    item,
    _summaryController.text,
    _isCompleteController.value,
    _priority)),
    ],
    ),
    ),
    ],
    )));
    }
    Future<void> update(BuildContext context, RealmServices realmServices,
    Item item, String summary, bool isComplete, int? priority) async {
    if (_formKey.currentState!.validate()) {
    await realmServices.updateItem(item,
    summary: summary, isComplete: isComplete, priority: priority);
    Navigator.pop(context);
    }
    }
    void delete(RealmServices realmServices, Item item, BuildContext context) {
    realmServices.deleteItem(item);
    Navigator.pop(context);
    }
    }
  4. lib/components/todo_item.dart内のItemCardウィジェットで、優先順位をつけるための可視化インジケーターを追加します。アイテムの優先順位をつける可視化インジケーターを付与する新たなウィジェット_PriorityIndicatorを作成します。

    先ほど作成した_PriorityIndicatorウィジェットをTodoItemウィジェットに追加します。

    lib/components/todo_item.dart
    // ... imports
    enum MenuOption { edit, delete }
    class TodoItem extends StatelessWidget {
    final Item item;
    const TodoItem(this.item, {Key? key}) : super(key: key);
    @override
    Widget build(BuildContext context) {
    final realmServices = Provider.of<RealmServices>(context);
    bool isMine = (item.ownerId == realmServices.currentUser?.id);
    return item.isValid
    ? ListTile(
    // ... leading property and child content
    title: Row(
    children: [
    Padding(
    padding: const EdgeInsets.only(right: 8.0),
    child: _PriorityIndicator(item.priority),
    ),
    SizedBox(width: 175, child: Text(item.summary)),
    ],
    ),
    // ... subtitle, trailing, and shape properties with child content
    )
    : Container();
    }
    // ... handleMenuClick() function
    }
    class _PriorityIndicator extends StatelessWidget {
    final int? priority;
    const _PriorityIndicator(this.priority, {Key? key}) : super(key: key);
    Widget getIconForPriority(int? priority) {
    if (priority == PriorityLevel.low) {
    return const Icon(Icons.keyboard_arrow_down, color: Colors.blue);
    } else if (priority == PriorityLevel.medium) {
    return const Icon(Icons.circle, color: Colors.grey);
    } else if (priority == PriorityLevel.high) {
    return const Icon(Icons.keyboard_arrow_up, color: Colors.orange);
    } else if (priority == PriorityLevel.severe) {
    return const Icon(
    Icons.block,
    color: Colors.red,
    );
    } else {
    return const SizedBox.shrink();
    }
    }
    @override
    Widget build(BuildContext context) {
    return getIconForPriority(priority);
    }
    }
3

アプリケーションを再度実行する前に、ホットリスタートを実行します。これにより、新しいスキーマで同期セッションが再起動し、同期エラーを防ぐことができます。

このチュートリアルで以前に作成したアカウントを使ってログインします。過去に作成した 1 つのアイテムが表示されます。新しいアイテムを追加すると、優先順位を設定できるようになります。優先順位を High にし、アイテムを保存します。

ブラウザで Atlas データページに切り替え、 Itemコレクションを更新します。 これでpriorityフィールドが追加され、 1に設定された新しいアイテムが表示されます。 また、次のスクリーンショットに示すように、既存のアイテムにpriorityフィールドも追加され、 nullに設定されていることにも注意してください。

コレクション内の 2 つのアイテム
クリックして拡大します

注意

同期が中断されなかった理由

Realm オブジェクトにプロパティを追加しても重大な変更ではないため、クライアントをリセットする必要はありません。 テンプレート アプリでは開発モードが有効になっているため、クライアント Realm オブジェクトへの変更はサーバー側のスキーマに反映されます。 詳しくは、「開発モードデータモデルの更新 」を参照してください。

優先順位フィールドを追加したため、Device Sync サブスクリプションを更新して、優先度が「高」または「重要」とマークされたアイテムのみを同期するようにします。

1

lib/realm/realm_services.dartファイルでは、ユーザーのデバイスおよびアカウントと同期するドキュメントを定義する Flexible Sync サブスクリプションを定義します。現在は、ownerプロパティが認証されたユーザーに一致するすべてのドキュメントを同期しています。

現在のサブスクリプション:

lib/realm/realm_services.dart
Future<void> updateSubscriptions() async {
realm.subscriptions.update((mutableSubscriptions) {
mutableSubscriptions.clear();
if (showAll) {
mutableSubscriptions.add(realm.all<Item>(), name: queryAllName);
} else {
mutableSubscriptions.add(
realm.query<Item>(r'owner_id == $0', [currentUser?.id]),
name: queryMyItemsName);
}
});
await realm.subscriptions.waitForSynchronization();
}

ここで、高優先度および重大優先度のアイテムのみを同期するようにサブスクリプションを変更します。ご存知のとおり、優先順位フィールドのタイプはint で、最高優先順位("Severe")の値は 0、最低優先順位("Low")の値は 3 です。

int と優先順位プロパティを直接比較できます。そのために、優先順位が PriorityLevel.high (または 1)以下のアイテムを含むようにサブスクリプション クエリをリファクタリングします。また、サブスクリプションに新しい名前 "getMyHighPriorityItemsSubscription" を付けます。

サブスクリプションを更新して古いサブスクリプションを削除し、優先順位を使用する新しいサブスクリプションを追加します。

lib/realm/realm_services.dart
// ... imports
class RealmServices with ChangeNotifier {
static const String queryAllName = "getAllItemsSubscription";
static const String queryMyItemsName = "getMyItemsSubscription";
static const String queryMyHighPriorityItemsName =
"getMyHighPriorityItemsSubscription";
bool showAll = false;
bool offlineModeOn = false;
bool isWaiting = false;
late Realm realm;
User? currentUser;
App app;
RealmServices(this.app) {
if (app.currentUser != null || currentUser != app.currentUser) {
currentUser ??= app.currentUser;
realm = Realm(Configuration.flexibleSync(currentUser!, [Item.schema]));
showAll = (realm.subscriptions.findByName(queryAllName) != null);
// Check if subscription previously exists on the realm
final subscriptionDoesNotExists =
(realm.subscriptions.findByName(queryMyHighPriorityItemsName) ==
null);
if (realm.subscriptions.isEmpty || subscriptionDoesNotExists) {
updateSubscriptions();
}
}
}
Future<void> updateSubscriptions() async {
realm.subscriptions.update((mutableSubscriptions) {
mutableSubscriptions.clear();
if (showAll) {
mutableSubscriptions.add(realm.all<Item>(), name: queryAllName);
} else {
mutableSubscriptions.add(
realm.query<Item>(
r'owner_id == $0 AND priority <= $1',
[currentUser?.id, PriorityLevel.high],
),
name: queryMyHighPriorityItemsName);
}
});
await realm.subscriptions.waitForSynchronization();
}
// ... other methods
}
2

アプリケーションを再度実行します。このチュートリアルの前半で作成したアカウントを使用してログインします。

Realm がドキュメントコレクションを再同期する最初の瞬間、以下のようなエラーメッセージが表示される場合があります。

The following RangeError was thrown building StreamBuilder<RealmResultsChanges<Item>>(dirty, state:
_StreamBuilderBaseState<RealmResultsChanges<Item>, AsyncSnapshot<RealmResultsChanges<Item>>>#387c4):
RangeError (index): Invalid value: Only valid value is 0: 3

このエラーは、サブスクリプション更新時に StreamBuilder ウィジェットで発生する可能性があります。製品アプリでは、エラー処理を追加できます。ただし、このチュートリアルでは、ホットリフレッシュを実行するだけでエラーが解消されます。

これで、作成した優先順位の高い新しいアイテムが表示されるはずです。

Tip

開発者モードが有効になっている場合にサブスクリプションを変更する

このチュートリアルでは、サブスクリプションを変更し、優先順位フィールドを初めてクエリすると、フィールドは Device Sync Collection Queryable Fieldsに自動的に追加されます。 これは、テンプレート アプリで開発モードがデフォルトで有効になっているために発生します。 開発モードが有効になっていない場合、クライアント側の同期クエリで使用するには、フィールドをクエリ可能なフィールドとして手動で追加する必要があります。

詳細については、「クエリ可能なフィールド 」を参照してください。

機能をさらにテストしたい場合は、さまざまな優先度のアイテムを作成できます。優先順位の低い新しいアイテムがアイテム リストに一時的に表示され、その後消えます。Realm はアイテムをローカルに作成し、バックエンドと同期した後、サブスクリプション ルールを満たしていないためアイテムを削除します。これを書き込み補正と言います。

また、最初に作成したドキュメントは優先順位が null になっているため、同期されないことにも注意してください。このアイテムを同期する場合は、Atlas UI でドキュメントを編集して優先順位フィールドに値を追加するか、サブスクリプションを変更して null 値を持つドキュメントを含めることができます。また、サブスクリプションに新しい名前 "getUserItemsWithHighOrNoPriority" を付けます。

lib/realm/realm_services.dart
class RealmServices with ChangeNotifier {
static const String queryAllName = "getAllItemsSubscription";
static const String queryMyItemsName = "getMyItemsSubscription";
static const String queryMyHighPriorityItemsName =
"getMyHighPriorityItemsSubscription";
static const String queryMyHighOrNoPriorityItemsName =
"getMyHighOrNoPriorityItemsSubscription";
bool showAll = false;
bool offlineModeOn = false;
bool isWaiting = false;
late Realm realm;
User? currentUser;
App app;
RealmServices(this.app) {
if (app.currentUser != null || currentUser != app.currentUser) {
currentUser ??= app.currentUser;
realm = Realm(Configuration.flexibleSync(currentUser!, [Item.schema]));
// Check if subscription previously exists on the realm
final subscriptionDoesNotExists =
realm.subscriptions.findByName(queryMyHighOrNoPriorityItemsName) ==
null;
if (realm.subscriptions.isEmpty || subscriptionDoesNotExists) {
updateSubscriptions();
}
}
}
Future<void> updateSubscriptions() async {
realm.subscriptions.update((mutableSubscriptions) {
mutableSubscriptions.clear();
if (showAll) {
mutableSubscriptions.add(realm.all<Item>(), name: queryAllName);
} else {
mutableSubscriptions.add(
realm.query<Item>(
r'owner_id == $0 AND priority IN {$1, $2, $3}',
[currentUser?.id, PriorityLevel.high, PriorityLevel.severe, null],
),
name: queryMyHighPriorityItemsName);
}
});
await realm.subscriptions.waitForSynchronization();
}
// ... other methods
}

繰り返しになりますが、新しいサブスクリプションで初めてアプリを開いたときに StreamBuilder エラーが発生した場合は、ホットリフレッシュを実行して期待されるデータを確認してください。

既存の Realm オブジェクトにプロパティを追加することは重大じゃない変更であり、 開発モード によってスキーマの変更がサーバー側に反映されるようになります。

注意

フィードバックの共有

ではどのようにGoしましたか。 ページ右下にあるRate this pageウィジェットを使用して、有効性を評価します。 またはGithub リポジトリ に問題を報告する 問題が発生した場合は、。

次へ

Atlas アプリケーション サービスとは