Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ /

在背景中同步 Realm - Java SDK

在此页面上

  • 先决条件
  • 例子
  • 同步逻辑
  • Worker

如果您需要在应用未运行时同步数据,您可以在背景进程中同步 Realm。

要开始后台同步,您需要将以下依赖项添加到您的 Android 应用程序中:

  • androidx.work:work-runtime ,将作业排入队列

  • androidx.concurrent:concurrent-futures ,从背景工作线程返回作业结果

背景同步需要满足两个条件:

  • 同步逻辑

  • 定期执行该逻辑的计划作业。

首先,编写同步 Realm 的自定义逻辑。 将此逻辑视为与后端的独立运行的实例连接。因此,您需要:

  • 初始化 Realm 软件开发工具包(Realm SDK)

  • 对用户进行身份验证以打开 Realm

如果用户最近使用过该应用,则可以使用缓存的用户档案。

打开 域,然后使用SyncSession.downloadAllServerChanges()SyncSession.uploadAllLocalChanges()将 域 与后端完全同步。

您可以使用 ListenableWorker 的子类将此逻辑作为背景进程执行 。将同步逻辑放入工作线程的 startWork()方法中:

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.concurrent.futures.ResolvableFuture;
import androidx.work.ListenableWorker;
import androidx.work.WorkerParameters;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.TimeUnit;
import io.realm.Realm;
import io.realm.mongodb.App;
import io.realm.mongodb.AppConfiguration;
import io.realm.mongodb.Credentials;
import io.realm.mongodb.User;
import io.realm.mongodb.sync.SyncConfiguration;
public class RealmBackgroundWorker extends ListenableWorker {
static final String UNIQUE_WORK_NAME = "RealmBackgroundWorker";
private ResolvableFuture<Result> future;
public RealmBackgroundWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@SuppressLint("RestrictedApi")
@NonNull
@Override
public ListenableFuture<Result> startWork() {
future = ResolvableFuture.create();
Realm.init(this.getApplicationContext());
String appID = YOUR_APP_ID; // replace this with your App ID
App app = new App(new AppConfiguration.Builder(appID).build());
Credentials credentials = Credentials.anonymous();
app.loginAsync(credentials, it -> {
if (it.isSuccess()) {
Log.v("EXAMPLE", "Successfully authenticated.");
User user = app.currentUser();
SyncConfiguration config = new SyncConfiguration.Builder(user, "PARTITION")
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm for background synchronization.");
try {
app.getSync().getSession(config).downloadAllServerChanges();
app.getSync().getSession(config).uploadAllLocalChanges();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} else {
Log.e("EXAMPLE", "Failed login: " + it.getError().getErrorMessage());
}
});
return future;
}
}
import android.annotation.SuppressLint
import android.content.Context
import android.util.Log
import androidx.concurrent.futures.ResolvableFuture
import androidx.work.ListenableWorker
import androidx.work.WorkerParameters
import com.google.common.util.concurrent.ListenableFuture
import io.realm.Realm
import io.realm.mongodb.App
import io.realm.mongodb.AppConfiguration
import io.realm.mongodb.Credentials
import io.realm.mongodb.User
import io.realm.mongodb.sync.SyncConfiguration
import java.util.concurrent.TimeUnit
class RealmBackgroundWorker(context: Context, workerParams: WorkerParameters) :
ListenableWorker(context, workerParams) {
private lateinit var future: ResolvableFuture<Result>
@SuppressLint("RestrictedApi")
override fun startWork(): ListenableFuture<Result> {
future = ResolvableFuture.create()
Realm.init(this.applicationContext)
val appID = YOUR_APP_ID // replace this with your App ID
val app = App(AppConfiguration.Builder(appID).build())
val credentials = Credentials.anonymous()
app.loginAsync(credentials) { it: App.Result<User?> ->
if (it.isSuccess) {
Log.v("EXAMPLE", "Successfully authenticated.")
val user = app.currentUser()
val config = SyncConfiguration.Builder(user, "PARTITION")
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm for background synchronization.")
try {
app.sync.getSession(config).downloadAllServerChanges()
app.sync.getSession(config).uploadAllLocalChanges()
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
})
} else {
Log.e("EXAMPLE", "Failed login: " + it.error.errorMessage)
}
}
return future
}
companion object {
const val UNIQUE_WORK_NAME = "RealmBackgroundWorker"
}
}

要创建定期执行背景同步的工作线程:

  1. 创建一组约束,指定工作线程所需的条件。

  2. 指定工作线程的执行频率。

  3. 使用 Android 操作系统对您的工作线程进行排队。 为其分配唯一标识符,以便将来更新作业。

您可以在应用程序的应用程序子类内创建背景同步作业,以保证每次运行应用程序时逻辑仅执行一次。

由于同步域会使用数据,因此应考虑仅当设备启动时在背景下载更改:

  • 电池电量低

  • 使用计量数据源

使用 约束 来描述背景同步运行的环境。

重复间隔取决于 Realm 中数据更新的频率以及用户打开应用程序的频率。 如果域全天频繁更新,请考虑将重复间隔设置为 1-3 小时。如果域每天仅更新少量内容,则最好设置较高的重复间隔,并且每天仅进行一到两次背景同步。

Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.build();
PeriodicWorkRequest backgroundRealmSync =
new PeriodicWorkRequest
.Builder(RealmBackgroundWorker.class,
// repeat every 12 hours
12, TimeUnit.HOURS,
// execute job at any point during that 12 hour period
12, TimeUnit.HOURS)
.setConstraints(constraints)
.build();
// enqueue the work job, replacing it with the most recent version if we update it
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
RealmBackgroundWorker.UNIQUE_WORK_NAME,
ExistingPeriodicWorkPolicy.REPLACE,
backgroundRealmSync);
val constraints: Constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.build()
val backgroundRealmSync: PeriodicWorkRequest = PeriodicWorkRequest.Builder(
RealmBackgroundWorker::class.java,
// repeat every 12 hours
12, TimeUnit.HOURS,
// execute job at any point during that 12 hour period
12, TimeUnit.HOURS
)
.setConstraints(constraints)
.build()
// enqueue the work job, replacing it with the most recent version if we update it
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
RealmBackgroundWorker.UNIQUE_WORK_NAME,
ExistingPeriodicWorkPolicy.REPLACE,
backgroundRealmSync
)

后退

检查网络连接