快速入门 - Java SDK
提示
本指南不使用 Device Sync
本指南可以帮助您开始使用 设备本地Realm。 如果您的应用程序需要使用 Atlas Device Sync 、 Realm Functions 或用户管理等功能通过网络与后端应用进行通信,则应遵循Sync 快速入门指南。
此页面包含快速将 Realm 集成到您的应用程序中的信息。 开始之前,请确保您已:
初始化 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>
定义对象模型
应用程序的数据模型定义了Realm中存储的数据结构。 您可以使用Realm对象模型通过应用程序代码中的Kotlin或Java类来定义应用程序的数据模型模型。
要定义应用程序的数据模型,请将以下类定义添加到应用程序代码中:
import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; import io.realm.annotations.Required; public class Task extends RealmObject { private String name; private String status = TaskStatus.Open.name(); public void setStatus(TaskStatus status) { this.status = status.name(); } public String getStatus() { return this.status; } 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() : RealmObject() { var name: String = "task" 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 } }
打开 Realm
使用RealmConfiguration
控制要打开的域的细节,包括域的名称或位置、是否允许在用户界面线程上同步读取或写入域等等。
String realmName = "My Project"; RealmConfiguration config = new RealmConfiguration.Builder().name(realmName).build(); Realm backgroundThreadRealm = Realm.getInstance(config);
val realmName: String = "My Project" val config = RealmConfiguration.Builder().name(realmName).build() val backgroundThreadRealm : Realm = Realm.getInstance(config)
创建、读取、更新和删除对象
打开域后,您可以在 写事务(write transaction) 区块中修改该域内的 对象 。
重要
UI 线程上的同步读写
默认情况下,只能使用异步事务在应用程序的用户界面线程中读取或写入域。也就是说,除非您明确允许使用同步方法,否则您只能在 Android 应用程序的主线程中使用名称以单词 Async
结尾的 Realm
方法。
此限制是为了应用程序用户的利益:在 UI 线程上执行读写操作,可能导致 UI 交互无响应或速度缓慢,所以通常来说,最好以异步方式或在后台线程中处理这些操作。但是,如果应用程序需要在 UI 线程上使用同步 Realm 读取或写入,则可以通过以下 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() task.name = "New Task" 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()
要修改任务,请在写事务区块中更新其属性:
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.getName()).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("name", otherTask.name).findFirst()!! innerOtherTask.status = TaskStatus.Complete.name }
最后,您可以通过在写事务(write transaction)区块中调用deleteFromRealm()
方法来删除除任务:
Task yetAnotherTask = Tasks.get(0); String yetAnotherTaskName = yetAnotherTask.getName(); // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction( transactionRealm -> { Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo("_id", yetAnotherTaskName).findFirst(); innerYetAnotherTask.deleteFromRealm(); });
val yetAnotherTask: Task = tasks.get(0)!! val yetAnotherTaskName: String = yetAnotherTask.name // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction { transactionRealm -> val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo("name", yetAnotherTaskName).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}") } })
完整示例
如果您在新的 Android Studio 项目中运行此项目,则可以将此文件复制并粘贴到应用程序的MainActivity
中,但请记住:
在文件顶部为您自己的项目使用包声明
如果您使用的是 Java,请更新
Task
和TaskStatus
的import
语句
import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; import io.realm.annotations.Required; public class Task extends RealmObject { private String name; private String status = TaskStatus.Open.name(); public void setStatus(TaskStatus status) { this.status = status.name(); } public String getStatus() { return this.status; } 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 android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import io.realm.OrderedRealmCollectionChangeListener; import io.realm.Realm; import io.realm.RealmConfiguration; import io.realm.RealmResults; 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.java.Task; import com.mongodb.realm.examples.model.java.TaskStatus; public class MainActivity extends AppCompatActivity { Realm uiThreadRealm; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Realm.init(this); // context, usually an Activity or Application String realmName = "My Project"; RealmConfiguration config = new RealmConfiguration.Builder().name(realmName).build(); uiThreadRealm = Realm.getInstance(config); addChangeListenerToRealm(uiThreadRealm); FutureTask<String> Task = new FutureTask(new BackgroundQuickStart(), "test"); ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.execute(Task); } 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(); } public class BackgroundQuickStart implements Runnable { public void run() { String realmName = "My Project"; RealmConfiguration config = new RealmConfiguration.Builder().name(realmName).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.getName()).findFirst(); innerOtherTask.setStatus(TaskStatus.Complete); }); Task yetAnotherTask = Tasks.get(0); String yetAnotherTaskName = yetAnotherTask.getName(); // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction( transactionRealm -> { Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo("_id", yetAnotherTaskName).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 android.os.Bundle import androidx.appcompat.app.AppCompatActivity import android.util.Log import io.realm.* import io.realm.annotations.PrimaryKey import io.realm.annotations.Required import io.realm.kotlin.where import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.FutureTask class MainActivity : AppCompatActivity() { lateinit var uiThreadRealm: Realm override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Realm.init(this) // context, usually an Activity or Application val realmName: String = "My Project" val config = RealmConfiguration.Builder() .name(realmName) .build() uiThreadRealm = Realm.getInstance(config) addChangeListenerToRealm(uiThreadRealm) val task : FutureTask<String> = FutureTask(BackgroundQuickStart(), "test") val executorService: ExecutorService = Executors.newFixedThreadPool(2) executorService.execute(task) } 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() } class BackgroundQuickStart : Runnable { override fun run() { val realmName: String = "My Project" val config = RealmConfiguration.Builder().name(realmName).build() val backgroundThreadRealm : Realm = Realm.getInstance(config) val task : Task = Task() task.name = "New Task" 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("name", otherTask.name).findFirst()!! innerOtherTask.status = TaskStatus.Complete.name } val yetAnotherTask: Task = tasks.get(0)!! val yetAnotherTaskName: String = yetAnotherTask.name // all modifications to a realm must happen inside of a write block backgroundThreadRealm.executeTransaction { transactionRealm -> val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo("name", yetAnotherTaskName).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() : RealmObject() { var name: String = "task" 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.