打包 Realm - Flutter SDK
您可能希望在移动应用程序中播种一些初始数据,这些数据将在应用程序首次启动时提供给用户。 为此,您可以在 Flutter 应用程序中捆绑现有的 Realm 文件。
如果您的应用使用 同步域,您可能不希望对其进行捆绑。 有关更多信息,请参阅捆绑同步Realm部分。
捆绑本地 Realm
创建用于捆绑的 Realm 文件
使用与生产应用程序相同的Realm 对象模式创建一个新项目。 打开包含要捆绑的数据的现有 域 ,或创建新 域。
使用 Realm .config.path 获取域文件的路径 属性。
print("Bundling realm"); final config = Configuration.local([Car.schema], path: 'bundle.realm'); final realm = Realm(config); realm.write(() { realm.add(Car(ObjectId(), "Audi", model: 'A8')); realm.add(Car(ObjectId(), "Mercedes", model: 'G Wagon')); }); print("Bundled realm location: " + realm.config.path); realm.close();
提示
使用 Dart 独立运行的实例 SDK 创建捆绑 Realm
出于以下原因,您可能希望使用Dart Standalone SDK为 Flutter 应用程序创建捆绑 Realm:
创建捆绑 Realm 不需要任何 Flutter 用户界面元素。
Dart 独立运行的实例所需的样板代码少于 Flutter 项目
在生产应用程序中捆绑 Realm 文件
现在您已经拥有了包含“种子”数据的域副本,您需要将其与生产应用程序捆绑在一起。
将域文件添加到应用程序的 Flutter 资产 中 。示例,您可以在项目中的位置assets/bundled.realm
添加捆绑域 。
将对捆绑 域 的引用添加到pubspec.yaml
文件中,以将其包含在生产应用程序中:
flutter: assets: - realm/bundle.realm
从捆绑的 Realm 文件中打开 Realm
现在您已拥有应用中包含的 Realm 副本,您需要添加代码来使用它。
在部署带有捆绑 Realm 的应用程序之前,您需要从嵌入式资源中提取 Realm,将其保存到应用程序的数据位置,然后在应用程序中打开这个新 Realm。 以下代码展示了如何在应用程序启动期间执行此操作。
创建辅助函数 initBundledRealm
来检查应用程序中是否已存在捆绑 Realm,如果不存在则将其加载到应用程序中。 initBundledRealm
在调用使用 runApp() 加载应用程序的窗口小部件之前,先调用 。
// Also import Realm schema and Flutter widgets import 'package:flutter/services.dart'; import 'package:realm/realm.dart'; import 'dart:io'; Future<Realm> initBundledRealm(String assetKey) async { final config = Configuration.local([Car.schema]); final file = File(config.path); if (!await file.exists()) { final realmBytes = await rootBundle.load(assetKey); await file.writeAsBytes( realmBytes.buffer .asUint8List(realmBytes.offsetInBytes, realmBytes.lengthInBytes), mode: FileMode.write); } return Realm(config); } void main() async { WidgetsFlutterBinding.ensureInitialized(); final realm = await initBundledRealm("assets/bundle.realm"); runApp(const MyApp()); }
捆绑同步 Realm
在大多数情况下,您不应捆绑同步域。 如果捆绑域的上次更新时间早于客户端最大离线时间,则用户在首次打开捆绑域文件时会遇到客户端重置。 客户端重置会导致应用程序从应用程序后端下载的完整状态。 这就抵消了捆绑域文件的优势。
您可以使用同步订阅向应用程序填充数据,而不是捆绑同步 Realm。 如果使用同步订阅添加数据,则无需担心数据早于客户端最大在线时间,同时可利用 Flexible Sync 的修剪功能。 要了解有关使用同步订阅的更多信息,请参阅管理同步订阅。
仅当您的使用案例满足以下条件时,才应捆绑同步域:
您可以确保用户拥有的应用程序版本附带捆绑的同步 Realm,该 Realm 创建时间晚于客户端最大离线时间。
初始捆绑数据非常大,并且应用程序是在互联网带宽有限的情况下使用的,因此使用同步订阅下载初始数据会花费太长时间。
所有应用用户都具有查看捆绑包中包含的数据的后端权限。 如果用户没有查看此数据的权限,则当域通过补偿写入错误与 Atlas 同步时,该数据将从其设备中删除。
要捆绑同步 Realm,请执行以下操作:
连接到您的 App Services App 并对用户进行身份验证。
将订阅添加到 Realm。 您需要订阅才能写入同步 Realm。
将数据添加到同步 Realm。
等待所有本地更改与 Device Sync 服务器同步。
使用 Realm.writeCopy() 创建同步 Realm 的新版本。您必须使用
Realm.writeCopy()
捆绑同步 Realm,因为该方法会删除将 Realm 与用户关联的元数据,而其他用户也可以通过这些元数据打开该 Realm 文件。
print("Bundling synced realm"); // You must connect to the Device Sync server with an authenticated // user to work with the synced realm. final app = App(AppConfiguration(APP_ID)); // Check if current user exists and log anonymous user if not. final user = app.currentUser ?? await app.logIn(Credentials.anonymous()); final config = Configuration.flexibleSync(user, [Car.schema]); final realm = Realm(config); // Add subscription that match the data being added // and your app's backend permissions. realm.subscriptions.update((mutableSubscriptions) { mutableSubscriptions.add(realm.all<Car>()); }); await realm.subscriptions.waitForSynchronization(); // Add data to realm realm.write(() { realm.add(Car(ObjectId(), "Audi", model: 'A8')); realm.add(Car(ObjectId(), "Mercedes", model: 'G Wagon')); }); // Sync changes with the server await realm.syncSession.waitForUpload(); await realm.syncSession.waitForDownload(); // Create new configuration for the bundled realm. // You must specify a path separate from the realm you // are copying for Realm.writeCopy() to succeed. final bundledConfig = Configuration.flexibleSync(user, [Car.schema], path: 'sync_bundle.realm'); realm.writeCopy(bundledConfig); print("Bundled realm location: " + bundledConfig.path); realm.close();
创建捆绑 Realm 后,请按照上述在生产应用程序中捆绑 Realm 文件 和从捆绑 Realm 文件中打开 Realm部分的说明进行操作。