동기화를 통한 빠른 시작 - Java SDK
팁
이 가이드에서는 Realm Mobile Sync를 사용합니다.
이 가이드 는 앱 백엔드 와 통신하는 Android 애플리케이션 을 시작하는 데 도움이 됩니다. 앱은 동기화, Realm 함수 및 사용자 관리 와 같은 기능을 제공합니다. 애플리케이션 에 로컬 데이터베이스 기능만 필요한 경우 빠른 시작(로컬 전용) 가이드 를 참조하세요.
이 페이지에는 Atlas App Services를 앱에 빠르게 통합하기 위한 정보가 포함되어 있습니다. 시작하기 전에 다음 사항을 확인하세요.
Realm 초기화
앱에서 Realm을 사용하려면 먼저 Realm 라이브러리를 초기화해야 합니다. 애플리케이션은 애플리케이션이 실행될 때마다 Realm을 한 번만 초기화해야 합니다.
Realm 라이브러리를 초기화하려면 Realm.init()
정적 함수에 Android context
를 제공합니다. 동작의 차이 없이 초기화를 위해 활동, 프래그먼트 또는 애플리케이션 context
을(를) 제공할 수 있습니다. 애플리케이션 onCreate()
서브클래스 의 메서드에서 Realm 라이브러리를 초기화할 수 있습니다. 애플리케이션 이 실행될 때마다 Realm 을 한 번만 초기화하도록 합니다.
Realm.init(this); // context, usually an Activity or Application
Realm.init(this) // context, usually an Activity or Application
팁
Android 매니페스트에 애플리케이션 서브클래스 등록
자체 Application
하위 클래스를 생성하는 경우 사용자 지정 애플리케이션 로직을 실행하려면 이를 애플리케이션의 AndroidManifest.xml
에 추가해야 합니다. 매니페스트 애플리케이션 정의의 android.name
속성을 설정하여 사용자가 애플리케이션을 실행할 때 Android가 다른 클래스보다 먼저 Application
하위 클래스를 인스턴스화하도록 합니다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mongodb.example"> <application android:name=".MyApplicationSubclass" ... /> </manifest>
앱 초기화
인증 및 동기화와 같은 App Services 기능을 사용하려면 앱 ID를 사용하여 App Services 앱에 액세스합니다. App Services UI에서 앱 ID 찾기를 수행할 수 있습니다.
app = new App(new AppConfiguration.Builder(appID) .build());
val appID : String = YOUR_APP_ID; app = App(AppConfiguration.Builder(appID) .build())
참고
Android Studio 오류?
Android Studio가 Realm
, App
또는 AppConfiguration
유형을 인식하지 못하는 경우 Gradle 빌드 구성에 문제가 있을 수 있습니다. 문제를 해결하려면 다음을 수행합니다.
다음으로 프로젝트를 정리하세요.
Build > Clean Project
Build > Rebuild Project
을(를) 사용하여 업데이트된build.gradle
파일을 기반으로 프로젝트를 다시 빌드합니다.Java SDK 설치 가이드를 다시 방문하여 종속성을 올바르게 설치했는지 확인합니다.
객체 모델 정의
애플리케이션의 Realm 데이터 모델 은 Realm에 저장되고 App Services와 동기화되는 데이터의 구조를 정의합니다. 애플리케이션의 Realm 데이터 모델은 두 가지 방법으로 정의할 수 있습니다.
App Services 의 스키마 를 통해
Realm 객체 모델을 사용하여 애플리케이션 코드에서 Kotlin 또는 Java 클래스를 통해
이 빠른 시작에서는 모바일 애플리케이션 코드의 클래스를 사용하여 스키마 를 정의하는 후자의 접근 방식을 사용합니다. 이러한 방식으로 앱의 객체 모델 을 정의하려면 개발 모드를 활성화 해야 합니다.
개발 모드를 활성화한 후 애플리케이션 코드에 다음 클래스 정의를 추가합니다.
import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; import io.realm.annotations.RealmClass; import io.realm.annotations.Required; import org.bson.types.ObjectId; public class Task extends RealmObject { private ObjectId _id = new ObjectId(); private String name = "Task"; private String status = TaskStatus.Open.name(); public void setStatus(TaskStatus status) { this.status = status.name(); } public String getStatus() { return this.status; } public ObjectId get_id() { return _id; } public void set_id(ObjectId _id) { this._id = _id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Task(String _name) { this.name = _name; } public Task() {} }
public enum TaskStatus { Open("Open"), InProgress("In Progress"), Complete("Complete"); String displayName; TaskStatus(String displayName) { this.displayName = displayName; } }
enum class TaskStatus(val displayName: String) { Open("Open"), InProgress("In Progress"), Complete("Complete"), } open class Task(_name: String = "Task", project: String = "My Project") : RealmObject() { var _id: ObjectId = ObjectId() var name: String = _name var status: String = TaskStatus.Open.name var statusEnum: TaskStatus get() { // because status is actually a String and another client could assign an invalid value, // default the status to "Open" if the status is unreadable return try { TaskStatus.valueOf(status) } catch (e: IllegalArgumentException) { TaskStatus.Open } } set(value) { status = value.name } }
사용자 인증
App Services UI 에서 익명 인증 을 활성화하면 사용자는 식별 정보를 제공하지 않고도 앱 에 즉시 로그 할 수 있습니다.
Credentials credentials = Credentials.anonymous(); app.loginAsync(credentials, result -> { if (result.isSuccess()) { Log.v("QUICKSTART", "Successfully authenticated anonymously."); User user = app.currentUser(); String partitionValue = "My Project"; SyncConfiguration config = new SyncConfiguration.Builder( user, partitionValue) .build(); uiThreadRealm = Realm.getInstance(config); addChangeListenerToRealm(uiThreadRealm); FutureTask<String> task = new FutureTask(new BackgroundQuickStart(app.currentUser()), "test"); ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.execute(task); } else { Log.e("QUICKSTART", "Failed to log in. Error: " + result.getError()); } });
val credentials: Credentials = Credentials.anonymous() app.loginAsync(credentials) { if (it.isSuccess) { Log.v("QUICKSTART", "Successfully authenticated anonymously.") val user: User? = app.currentUser() val partitionValue: String = "My Project" val config = SyncConfiguration.Builder(user, partitionValue) .build() uiThreadRealm = Realm.getInstance(config) addChangeListenerToRealm(uiThreadRealm) val task : FutureTask<String> = FutureTask(BackgroundQuickStart(app.currentUser()!!), "test") val executorService: ExecutorService = Executors.newFixedThreadPool(2) executorService.execute(task) } else { Log.e("QUICKSTART", "Failed to log in. Error: ${it.error}") } }
Realm은 사용자를 인증, 등록 및 연결할 수 있는 다양한 방법을 추가로 제공합니다.
Realm 열기
동기화를 활성화 하고 사용자를 인증하면 동기화된 영역 을 열 수 있습니다. SyncConfiguration
를 사용하여 시간 초과, UI 스레드의 동기 읽기 및 쓰기 등 애플리케이션 이 App Services 와 데이터를 동기화하는 방법에 대한 세부 사항을 제어합니다.
String partitionValue = "My Project"; SyncConfiguration config = new SyncConfiguration.Builder( user, partitionValue) .build(); Realm backgroundThreadRealm = Realm.getInstance(config);
val partitionValue: String = "My Project" val config = SyncConfiguration.Builder(user, partitionValue) .build() val backgroundThreadRealm : Realm = Realm.getInstance(config)
객체 만들기, 읽기, 업데이트 및 삭제
영역 을 연 후에는 쓰기 트랜잭션( 쓰기 트랜잭션 (write transaction) ) 차단 에서 해당 영역 내의 객체 를 수정할 수 있습니다.
중요
UI 스레드의 동기식 읽기 및 쓰기
기본적으로 비동기 트랜잭션을 사용하여 애플리케이션의 UI 스레드에서 영역에 읽기 또는 쓰기만 가능합니다. 즉, 동기 메서드의 사용을 명시적으로 허용하지 않는 한 Android 애플리케이션의 기본 스레드에서 이름이 Async
(이)라는 단어로 끝나는 Realm
메서드만 사용할 수 있습니다.
이러한 제한은 애플리케이션 사용자를 위해 존재합니다. 즉, UI 스레드에서 읽기 및 쓰기 작업을 수행하면 UI 상호 작용이 응답하지 않거나 느려질 수 있으므로 일반적으로 이러한 작업을 비동기적으로 처리하거나 배경 스레드에서 처리하는 것이 가장 좋습니다. 하지만 애플리케이션이 UI 스레드에서 동기 영역 읽기 또는 쓰기를 사용해야 하는 경우 다음 SyncConfiguration
옵션을 사용하여 동기 메서드 사용을 명시적으로 허용할 수 있습니다.
SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION) .allowQueriesOnUiThread(true) .allowWritesOnUiThread(true) .build(); Realm.getInstanceAsync(config, new Realm.Callback() { public void onSuccess(Realm realm) { Log.v( "EXAMPLE", "Successfully opened a realm with reads and writes allowed on the UI thread." ); } });
val config = SyncConfiguration.Builder(app.currentUser(), PARTITION) .allowQueriesOnUiThread(true) .allowWritesOnUiThread(true) .build() Realm.getInstanceAsync(config, object : Realm.Callback() { override fun onSuccess(realm: Realm) { Log.v("EXAMPLE", "Successfully opened a realm with reads and writes allowed on the UI thread.") } })
새 Task
을 만들려면 Task
클래스의 인스턴스를 인스턴스화하고 쓰기 블록의 Realm에 추가합니다.
Task task = new Task("New Task"); backgroundThreadRealm.executeTransaction (transactionRealm -> { transactionRealm.insert(task); });
val task : Task = Task("New Task", partitionValue) backgroundThreadRealm.executeTransaction { transactionRealm -> transactionRealm.insert(task) }
영역 에 있는 모든 항목의 라이브 컬렉션 을 조회 할 수 있습니다.
// all tasks in the realm RealmResults<Task> tasks = backgroundThreadRealm.where(Task.class).findAll();
// all tasks in the realm val tasks : RealmResults<Task> = backgroundThreadRealm.where<Task>().findAll()
필터를 사용하여 해당 컬렉션 을 필터하다 할 수도 있습니다 .
// you can also filter a collection RealmResults<Task> tasksThatBeginWithN = tasks.where().beginsWith("name", "N").findAll(); RealmResults<Task> openTasks = tasks.where().equalTo("status", TaskStatus.Open.name()).findAll();
// you can also filter a collection val tasksThatBeginWithN : List<Task> = tasks.where().beginsWith("name", "N").findAll() val openTasks : List<Task> = tasks.where().equalTo("status", TaskStatus.Open.name).findAll()
작업을 수정하려면 쓰기 트랜잭션(write transaction) 차단에서 해당 속성을 업데이트합니다.
Task otherTask = tasks.get(0); // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction( transactionRealm -> { Task innerOtherTask = transactionRealm.where(Task.class).equalTo("_id", otherTask.get_id()).findFirst(); innerOtherTask.setStatus(TaskStatus.Complete); });
val otherTask: Task = tasks[0]!! // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction { transactionRealm -> val innerOtherTask : Task = transactionRealm.where<Task>().equalTo("_id", otherTask._id).findFirst()!! innerOtherTask.status = TaskStatus.Complete.name }
마지막으로 쓰기 트랜잭션( 쓰기 트랜잭션 (write transaction) ) 차단 에서 deleteFromRealm()
메서드를 호출하여 작업 을 삭제 수 있습니다.
Task yetAnotherTask = tasks.get(0); ObjectId yetAnotherTaskId = yetAnotherTask.get_id(); // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction( transactionRealm -> { Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo("_id", yetAnotherTaskId).findFirst(); innerYetAnotherTask.deleteFromRealm(); });
val yetAnotherTask: Task = tasks.get(0)!! val yetAnotherTaskId: ObjectId = yetAnotherTask._id // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction { transactionRealm -> val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo("_id", yetAnotherTaskId).findFirst()!! innerYetAnotherTask.deleteFromRealm() }
변화를 주시하세요
addChangeListener()
메서드와 함께 사용자 지정 OrderedRealmCollectionChangeListener
를 첨부하여 영역, 컬렉션 또는 객체 의 변경 사항 을 확인할 수 있습니다.
// all tasks in the realm RealmResults<Task> tasks = uiThreadRealm.where(Task.class).findAllAsync(); tasks.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Task>>() { public void onChange(RealmResults<Task> collection, OrderedCollectionChangeSet changeSet) { // process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges(); for (OrderedCollectionChangeSet.Range range : deletions) { Log.v("QUICKSTART", "Deleted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); } OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges(); for (OrderedCollectionChangeSet.Range range : insertions) { Log.v("QUICKSTART", "Inserted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); } OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges(); for (OrderedCollectionChangeSet.Range range : modifications) { Log.v("QUICKSTART", "Updated range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); } } });
// all tasks in the realm val tasks : RealmResults<Task> = realm.where<Task>().findAllAsync() tasks.addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<Task>> { collection, changeSet -> // process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate val deletions = changeSet.deletionRanges for (i in deletions.indices.reversed()) { val range = deletions[i] Log.v("QUICKSTART", "Deleted range: ${range.startIndex} to ${range.startIndex + range.length - 1}") } val insertions = changeSet.insertionRanges for (range in insertions) { Log.v("QUICKSTART", "Inserted range: ${range.startIndex} to ${range.startIndex + range.length - 1}") } val modifications = changeSet.changeRanges for (range in modifications) { Log.v("QUICKSTART", "Updated range: ${range.startIndex} to ${range.startIndex + range.length - 1}") } })
로그아웃
로그인한 후 로그아웃할 수 있습니다.
app.currentUser().logOutAsync(result -> { if (result.isSuccess()) { Log.v("QUICKSTART", "Successfully logged out."); } else { Log.e("QUICKSTART", "Failed to log out, error: " + result.getError()); } });
app.currentUser()?.logOutAsync() { if (it.isSuccess) { Log.v("QUICKSTART", "Successfully logged out.") } else { Log.e("QUICKSTART", "Failed to log out, error: ${it.error}") } }
전체 예시
appId를 영역 애플리케이션 ID로 바꿔 전체 예시를 실행합니다. 새 Android Studio 프로젝트에서 이 프로젝트를 실행하는 경우 이 파일을 복사하여 애플리케이션의 MainActivity
에 붙여넣을 수 있습니다.
프로젝트와 일치하도록 패키지 선언을 변경합니다.
애플리케이션 ID 자리 표시자를 앱의 애플리케이션 ID로 바꿉니다.
Java를 사용하는 경우
Task
및TaskStatus
에 대한import
문을 업데이트합니다.
import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; import io.realm.annotations.RealmClass; import io.realm.annotations.Required; import org.bson.types.ObjectId; public class Task extends RealmObject { private ObjectId _id = new ObjectId(); private String name = "Task"; private String status = TaskStatus.Open.name(); public void setStatus(TaskStatus status) { this.status = status.name(); } public String getStatus() { return this.status; } public ObjectId get_id() { return _id; } public void set_id(ObjectId _id) { this._id = _id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Task(String _name) { this.name = _name; } public Task() {} }
public enum TaskStatus { Open("Open"), InProgress("In Progress"), Complete("Complete"); String displayName; TaskStatus(String displayName) { this.displayName = displayName; } }
import io.realm.OrderedCollectionChangeSet; import org.bson.types.ObjectId; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import io.realm.OrderedRealmCollectionChangeListener; import io.realm.Realm; import io.realm.RealmResults; 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.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import com.mongodb.realm.examples.model.Task; import com.mongodb.realm.examples.model.TaskStatus; public class MainActivity extends AppCompatActivity { Realm uiThreadRealm; App app; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Realm.init(this); // context, usually an Activity or Application app = new App(new AppConfiguration.Builder(appID) .build()); Credentials credentials = Credentials.anonymous(); app.loginAsync(credentials, result -> { if (result.isSuccess()) { Log.v("QUICKSTART", "Successfully authenticated anonymously."); User user = app.currentUser(); String partitionValue = "My Project"; SyncConfiguration config = new SyncConfiguration.Builder( user, partitionValue) .build(); uiThreadRealm = Realm.getInstance(config); addChangeListenerToRealm(uiThreadRealm); FutureTask<String> task = new FutureTask(new BackgroundQuickStart(app.currentUser()), "test"); ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.execute(task); } else { Log.e("QUICKSTART", "Failed to log in. Error: " + result.getError()); } }); } private void addChangeListenerToRealm(Realm realm) { // all tasks in the realm RealmResults<Task> tasks = uiThreadRealm.where(Task.class).findAllAsync(); tasks.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Task>>() { public void onChange(RealmResults<Task> collection, OrderedCollectionChangeSet changeSet) { // process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges(); for (OrderedCollectionChangeSet.Range range : deletions) { Log.v("QUICKSTART", "Deleted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); } OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges(); for (OrderedCollectionChangeSet.Range range : insertions) { Log.v("QUICKSTART", "Inserted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); } OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges(); for (OrderedCollectionChangeSet.Range range : modifications) { Log.v("QUICKSTART", "Updated range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); } } }); } protected void onDestroy() { super.onDestroy(); // the ui thread realm uses asynchronous transactions, so we can only safely close the realm // when the activity ends and we can safely assume that those transactions have completed uiThreadRealm.close(); app.currentUser().logOutAsync(result -> { if (result.isSuccess()) { Log.v("QUICKSTART", "Successfully logged out."); } else { Log.e("QUICKSTART", "Failed to log out, error: " + result.getError()); } }); } public class BackgroundQuickStart implements Runnable { User user; public BackgroundQuickStart(User user) { this.user = user; } public void run() { String partitionValue = "My Project"; SyncConfiguration config = new SyncConfiguration.Builder( user, partitionValue) .build(); Realm backgroundThreadRealm = Realm.getInstance(config); Task task = new Task("New Task"); backgroundThreadRealm.executeTransaction (transactionRealm -> { transactionRealm.insert(task); }); // all tasks in the realm RealmResults<Task> tasks = backgroundThreadRealm.where(Task.class).findAll(); // you can also filter a collection RealmResults<Task> tasksThatBeginWithN = tasks.where().beginsWith("name", "N").findAll(); RealmResults<Task> openTasks = tasks.where().equalTo("status", TaskStatus.Open.name()).findAll(); Task otherTask = tasks.get(0); // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction( transactionRealm -> { Task innerOtherTask = transactionRealm.where(Task.class).equalTo("_id", otherTask.get_id()).findFirst(); innerOtherTask.setStatus(TaskStatus.Complete); }); Task yetAnotherTask = tasks.get(0); ObjectId yetAnotherTaskId = yetAnotherTask.get_id(); // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction( transactionRealm -> { Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo("_id", yetAnotherTaskId).findFirst(); innerYetAnotherTask.deleteFromRealm(); }); // because this background thread uses synchronous realm transactions, at this point all // transactions have completed and we can safely close the realm backgroundThreadRealm.close(); } } }
import org.bson.types.ObjectId import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import android.util.Log import com.mongodb.realm.examples.YOUR_APP_ID import io.realm.OrderedRealmCollectionChangeListener import io.realm.Realm import io.realm.RealmObject import io.realm.RealmResults import io.realm.annotations.PrimaryKey import io.realm.annotations.Required import io.realm.kotlin.where 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.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.FutureTask class MainActivity : AppCompatActivity() { lateinit var uiThreadRealm: Realm lateinit var app: App override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Realm.init(this) // context, usually an Activity or Application val appID : String = YOUR_APP_ID; app = App(AppConfiguration.Builder(appID) .build()) val credentials: Credentials = Credentials.anonymous() app.loginAsync(credentials) { if (it.isSuccess) { Log.v("QUICKSTART", "Successfully authenticated anonymously.") val user: User? = app.currentUser() val partitionValue: String = "My Project" val config = SyncConfiguration.Builder(user, partitionValue) .build() uiThreadRealm = Realm.getInstance(config) addChangeListenerToRealm(uiThreadRealm) val task : FutureTask<String> = FutureTask(BackgroundQuickStart(app.currentUser()!!), "test") val executorService: ExecutorService = Executors.newFixedThreadPool(2) executorService.execute(task) } else { Log.e("QUICKSTART", "Failed to log in. Error: ${it.error}") } } } fun addChangeListenerToRealm(realm : Realm) { // all tasks in the realm val tasks : RealmResults<Task> = realm.where<Task>().findAllAsync() tasks.addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<Task>> { collection, changeSet -> // process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate val deletions = changeSet.deletionRanges for (i in deletions.indices.reversed()) { val range = deletions[i] Log.v("QUICKSTART", "Deleted range: ${range.startIndex} to ${range.startIndex + range.length - 1}") } val insertions = changeSet.insertionRanges for (range in insertions) { Log.v("QUICKSTART", "Inserted range: ${range.startIndex} to ${range.startIndex + range.length - 1}") } val modifications = changeSet.changeRanges for (range in modifications) { Log.v("QUICKSTART", "Updated range: ${range.startIndex} to ${range.startIndex + range.length - 1}") } }) } override fun onDestroy() { super.onDestroy() // the ui thread realm uses asynchronous transactions, so we can only safely close the realm // when the activity ends and we can safely assume that those transactions have completed uiThreadRealm.close() app.currentUser()?.logOutAsync() { if (it.isSuccess) { Log.v("QUICKSTART", "Successfully logged out.") } else { Log.e("QUICKSTART", "Failed to log out, error: ${it.error}") } } } class BackgroundQuickStart(val user: User) : Runnable { override fun run() { val partitionValue: String = "My Project" val config = SyncConfiguration.Builder(user, partitionValue) .build() val backgroundThreadRealm : Realm = Realm.getInstance(config) val task : Task = Task("New Task", partitionValue) backgroundThreadRealm.executeTransaction { transactionRealm -> transactionRealm.insert(task) } // all tasks in the realm val tasks : RealmResults<Task> = backgroundThreadRealm.where<Task>().findAll() // you can also filter a collection val tasksThatBeginWithN : List<Task> = tasks.where().beginsWith("name", "N").findAll() val openTasks : List<Task> = tasks.where().equalTo("status", TaskStatus.Open.name).findAll() val otherTask: Task = tasks[0]!! // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction { transactionRealm -> val innerOtherTask : Task = transactionRealm.where<Task>().equalTo("_id", otherTask._id).findFirst()!! innerOtherTask.status = TaskStatus.Complete.name } val yetAnotherTask: Task = tasks.get(0)!! val yetAnotherTaskId: ObjectId = yetAnotherTask._id // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction { transactionRealm -> val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo("_id", yetAnotherTaskId).findFirst()!! innerYetAnotherTask.deleteFromRealm() } // because this background thread uses synchronous realm transactions, at this point all // transactions have completed and we can safely close the realm backgroundThreadRealm.close() } } } enum class TaskStatus(val displayName: String) { Open("Open"), InProgress("In Progress"), Complete("Complete"), } open class Task(_name: String = "Task", project: String = "My Project") : RealmObject() { var _id: ObjectId = ObjectId() var name: String = _name var status: String = TaskStatus.Open.name var statusEnum: TaskStatus get() { // because status is actually a String and another client could assign an invalid value, // default the status to "Open" if the status is unreadable return try { TaskStatus.valueOf(status) } catch (e: IllegalArgumentException) { TaskStatus.Open } } set(value) { status = value.name } }
출력
위의 코드를 실행하면 다음과 유사한 출력이 생성됩니다.
Successfully authenticated anonymously. Updated range: 0 to 1 Deleted range: 0 to 1 Successfully logged out.