使用 Atlas Device Sync 时,Flutter SDK 使用同步会话在后台与 Atlas 同步数据。 每当您打开同步 Realm 时,同步会话就会启动。
同步会话管理以下内容:
上传和下载对同步数据库的更改
暂停和恢复同步
监控同步进度
监控网络连接
您可以通过Realm.syncSession属性访问权限任何同步域的 会话 。
先决条件
在托管同步会话状态之前,您必须执行以下操作:
等待更改上传和下载
要异步等待所有更改从同步域上传到Atlas ,请调用 Session.waitForUpload()。要异步等待 Atlas 上的所有更改下载到同步域,请调用 Session.waitForDownload().
// Wait to download all pending changes from Atlas await realm.syncSession.waitForDownload(); // Add data locally realm.write(() { realm.addAll<Car>([ Car(ObjectId(), "Hyundai"), Car(ObjectId(), "Kia"), Car(ObjectId(), "Lincoln") ]); }); // Wait for changes to upload to Atlas before continuing execution. await realm.syncSession.waitForUpload();
您可以为waitForUpload() 和 添加一个可选的 CancellationToken。waitForDownload()
final cancellationToken = CancellationToken(); final waitForDownloadFuture = realm.syncSession.waitForDownload(cancellationToken); cancellationToken.cancel(); final waitForUploadFuture = realm.syncSession.waitForUpload(cancellationToken); cancellationToken.cancel();
暂停和恢复同步会话
要暂停会话同步,请调用 Session.pause()。会话暂停时, 域不会与Atlas同步更改。
要恢复同步更改,请调用 Session.resume().。
您必须为要暂停和重新启动同步会话的每个 Realm 手动调用Session.pause()和Session.resume() 。 一个会话的同步状态对其他打开的会话没有影响。
以下代码块演示了如何调用这些方法:
// Pause the sync session realm.syncSession.pause(); // Data that you add while the sync session is paused does not sync to Atlas. // However, the data is still added to the realm locally. realm.write(() { realm.addAll<Car>([ Car(ObjectId(), "Volvo"), Car(ObjectId(), "Genesis"), Car(ObjectId(), "VW") ]); }); // Resume sync session. Now, the data you wrote to the realm // syncs to Atlas. realm.syncSession.resume();
何时暂停同步会话
对于大多数应用程序,无需手动暂停和恢复同步会话。 但是,在某些情况下,您可能希望暂停或暂停同步会话:
您只想在用户执行特定操作后进行同步
您只想在一天中的特定时间进行同步
您不想在网络连接较差时尝试同步
您想要显式强制同步会话连接
在网络连接较差的情况下,不断尝试建立网络连接可能会耗尽用户的设备电池。
显式强制同步会话连接的情况最常见与离线一段时间有关。同步客户端尝试连接,一旦失败,就会Go指数退避状态。长时间离线后,客户端可能无法立即重新连接。 暂停和恢复同步会话会显式强制连接。
当您暂停同步会话时,请记住以下事项:
暂停同步会话会使其在两个方向上暂停。您的应用在设备上所做的更改不会与后端同步,对后端或其他设备上的数据的更改也不会同步到设备。 无法仅暂停上传或仅暂停下载。
如果您希望客户端永久停止与后端同步,请勿暂停同步会话。 要永久停止同步,请将同步 Realm 的内容复制到非同步 Realm,并在客户端中使用该非同步 Realm。
请勿在不确定的时间段或以月和年为单位的时间范围内通过暂停同步来停止同步。 该功能不是针对这些使用案例而设计或测试的。 以这种方式使用时,您可能会遇到一系列问题。
监控同步上传和下载进度
在版本2.0.0中进行了更改: 已弃用transferredBytes和transferrableBytes ,改用progressEstimate
要监控同步进度,请调用 SyncSession.getProgressStream() 。此方法返回 SyncProgress 对象流,该对象为当前上传或下载提供 progressEstimate。
提供的progressEstimate是一个双精度值,其值范围为0.0到1.0 。 在1.0时,进度流已完成。
SyncSession.getProgressStream() 有两个参数:
可设立为
upload或download的 ProgressDirection枚举。指定进度流是监控上传还是下载进度。ProgressMode枚举,可设立为以下之一:
reportIndefinitely:将通知设置为继续,直到取消注册回调。forCurrentlyOutstandingWork:将通知设置为继续,直到progressEstimate达到1.0。
final stream = realm.syncSession.getProgressStream( ProgressDirection.upload, ProgressMode.forCurrentlyOutstandingWork); double progressEstimate = -1; late StreamSubscription streamListener; streamListener = stream.listen((syncProgressEvent) { progressEstimate = syncProgressEvent.progressEstimate; if (progressEstimate < 1.0) { print('Upload progress: ${progressEstimate * 100}%'); } }, onDone: () { print('Upload progress: ${progressEstimate * 100}%'); print("Upload complete"); }, onError: (error) { print("An error occurred: $error"); streamListener.cancel(); });
提示
您还可以在首次打开Realm时使用onProgressCallback配置同步监控。
监控网络连接
您可以使用 Session.connectionState 获取当前网络连接的状态。这将返回一个包含网络连接状态的ConnectionState枚举:connected、disconnected 或 connecting。
if (realm.syncSession.connectionState == ConnectionState.connected) { // ... do stuff }
使用 Session.connectionStateChanges 监控网络连接状态。此属性返回 ConnectionStateChange 对象的 Stream,该对象会在网络连接更改时更新。您可以从 ConnectionStateChange访问权限当前和以前的 ConnectionState。
final connectionStream = realm.syncSession.connectionStateChanges; late StreamSubscription streamListener; streamListener = connectionStream.listen((connectionStateChange) { if (connectionStateChange.current == ConnectionState.connected) { print("Connected to Atlas Device Sync server"); streamListener.cancel(); } });
手动重新连接所有同步会话
Flutter SDK 会自动检测设备何时在离线后重新获得连接,并尝试使用增量退避策略重新连接。
您可以选择使用 App.reconnect() 手动触发重新连接尝试,而不是等待增量退避的持续时间。如果您对网络状况有更准确的了解并且不想依赖自动重新连接检测,这非常有用。
app.reconnect();
调用此方法时,SDK 会强制所有同步会话立即尝试重新连接,并重置用于增量退避的任何计时器。
重要
无法在套接字读取超时时间内重新连接
Flutter SDK 的内部默认套接字读取超时为 2 分钟,如果读取操作在 2 分钟窗口内未收到任何数据,SDK 将超时。 如果您在该窗口内调用App.Sync.reconnect() ,Flutter SDK不会尝试重新连接。