백그라운드에서 Realm 동기화 - Java SDK
앱이 실행되지 않을 때 데이터를 동기화해야 하는 경우 백그라운드 프로세스에서 Realm을 동기화할 수 있습니다.
전제 조건
백그라운드 동기화를 시작하려면 Android 애플리케이션에 다음 종속성을 추가해야 합니다.
androidx.work:work-runtime, 작업을 대기열에 추가
androidx.concurrent:concurrent-futures, 배경 작업자의 작업 결과를 반환합니다.
예시
백그라운드 동기화에는 두 가지가 필요합니다.
동기화 로직
해당 로직을 주기적으로 수행하는 예약된 작업입니다.
동기화 로직
먼저 영역을 동기화하는 사용자 지정 로직을 작성합니다. 이 로직을 백엔드에 대한 독립형 연결로 취급합니다. 따라서 다음을 수행해야 합니다.
Realm SDK 초기화
영역을 열기 위한 사용자 인증
사용자가 최근에 앱을 사용한 경우 사용자의 캐시된 자격 증명을 사용할 수 있습니다.
영역을 연 다음 SyncSession.downloadAllServerChanges() 를 사용합니다. 및 SyncSession.uploadAllLocalChanges() 를 사용하여 영역을 백엔드와 완전히 동기화합니다.
ListenerableWorker 의 하위 클래스를 사용하여 이 로직을 배경 프로세스 로 실행할 수 있습니다. . 동기화 로직을 작업자의 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( Context context, WorkerParameters workerParams) { super(context, workerParams); } 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() { 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> 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" } }
작업자
주기적으로 백그라운드 동기화를 수행하는 작업자를 만들려면 다음 안내를 따르세요.
작업자에게 필요한 조건을 지정하는 제약 조건 세트를 생성합니다.
작업자가 실행해야 하는 빈도를 지정합니다.
Android OS에 작업자를 대기열에 추가합니다. 나중에 작업을 업데이트할 수 있도록 고유 식별자를 할당합니다.
앱의 애플리케이션 하위 클래스 내에서 백그라운드 동기화 작업을 만들어 애플리케이션이 실행될 때마다 로직이 한 번만 실행되도록 할 수 있습니다.
영역 동기화에는 데이터가 사용되므로 기기가 다음과 같지 않을 때만 백그라운드에서 변경 사항을 다운로드하는 것을 고려해야 합니다.
배터리 부족
측정 데이터 소스 사용
제약 조건 사용 배경 동기화 가 실행되는 환경을 설명합니다.
반복 간격은 Realm에서 데이터가 업데이트되는 빈도와 사용자가 애플리케이션을 여는 빈도에 따라 달라집니다. 영역이 하루 종일 자주 업데이트되는 경우 반복 간격을 1~3시간으로 설정하는 것이 좋습니다. Realm이 하루에 적은 횟수만 업데이트하는 경우 반복 간격을 높게 설정하고 하루에 한 두 번 백그라운드 동기화만 설정하는 것이 가장 좋습니다.
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 )