Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ /

Sincronizar um Realm em segundo plano - Java SDK

Nesta página

  • Pré-requisitos
  • Exemplo
  • Lógica de sincronização
  • Trabalhador

Se você precisar sincronizar dados quando seu aplicativo não estiver em execução, poderá sincronizar realms em um processo de background.

Para começar a usar a sincronização em segundo plano, é necessário adicionar as seguintes dependências ao seu aplicativo Android:

  • androidx.work:work-runtime, para enfileirar tarefas

  • androidx.concurrent:concurrent-futures, para retornar os resultados da tarefa de um trabalhador em background

A sincronização em segundo plano requer duas coisas:

  • lógica de sincronização

  • uma tarefa agendada que executa periodicamente essa lógica.

Primeiro, escreva a lógica personalizada que sincroniza seu Realm. Trate essa lógica como uma conexão autônomo com seu backend. Como resultado, você precisará:

  • inicializar o Realm SDK

  • autenticar um usuário para abrir o Realm

Você pode usar as credenciais em cache de um usuário se o usuário tiver usado o aplicativo recentemente.

Abra o Realm e use SyncSession.downloadAllServerChanges() e SyncSession.uploadAllLocalChanges() para sincronizar o Realm totalmente com o backend.

Você pode executar essa lógica como um processo de background usando uma subclasse de ListenableWorker. Coloque sua lógica de sincronização no método startWork() do seu trabalhador:

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"
}
}

Para criar um operador que executa periodicamente a sincronização em segundo plano:

  1. Crie um conjunto de restrições que especifique as condições necessárias para o seu funcionário.

  2. Especifique com que frequência seu funcionário deve executar.

  3. Anexe seu operador com o sistema operacional Android. Atribua a ele um identificador exclusivo para que você possa atualizar a tarefa no futuro.

Você pode criar a tarefa de sincronização em segundo plano dentro de uma subclasse Application em seu aplicativo para garantir que a lógica seja executada somente uma vez a cada execução do aplicativo.

Como a sincronização de um Realm usa dados, considere baixar as alterações em segundo plano apenas quando o dispositivo não estiver:

  • bateria fraca

  • usando um conjunto de dados com medição

Restrições de uso para descrever o ambiente em que sua sincronização em segundo plano é executada.

O intervalo repetido depende da frequência com que os dados são atualizados no Realm e com que frequência os usuários abrem sua aplicação. Se o Realm for atualizado com frequência ao longo do dia, considere definir um intervalo repetido de 1 a 3 horas. Se o Realm atualizar apenas um pequeno número de vezes por dia, é melhor definir um intervalo de repetição maior e apenas sincronizar em segundo plano uma ou duas vezes por dia.

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
)

Voltar

Verifique a conexão de rede