打开和关闭 Realm — Java SDK
与 Android 应用程序中的 Realm 交互使用以下一系列高级步骤:
为要打开的 Realm 创建配置。
通过 config 打开 Realm。
完成后,关闭 Realm以释放资源。
默认 Realm
您可以使用 setDefaultConfiguration() 方法将任何 RealmConfiguration 或 SyncConfiguration 保存为应用程序的默认值:
RealmConfiguration config = new RealmConfiguration.Builder() .name("default-realm") .allowQueriesOnUiThread(true) .allowWritesOnUiThread(true) .compactOnLaunch() .inMemory() .build(); // set this config as the default realm Realm.setDefaultConfiguration(config);
val config = RealmConfiguration.Builder() .name("default-realm") .allowQueriesOnUiThread(true) .allowWritesOnUiThread(true) .compactOnLaunch() .inMemory() .build() // set this config as the default realm Realm.setDefaultConfiguration(config)
然后,你可以使用 getDefaultConfiguration () 来访问该配置,或者使用 getDefaultInstance() 来打开一个具有该配置的域:
Realm realm = Realm.getDefaultInstance(); Log.v("EXAMPLE","Successfully opened the default realm at: " + realm.getPath());
val realm = Realm.getDefaultInstance() Log.v("EXAMPLE","Successfully opened the default realm at: ${realm.path}")
本地 Realm
本地域仅在客户端设备上存储数据。您可以使用 RealmConfiguration
自定义本地域的设置。
本地 Realm 配置
要配置 Realm 的设置,请使用 RealmConfiguration.Builder 创建 RealmConfiguration 。以下示例将本地 Realm 配置为:
文件名“alternate-realm”
用户界面线程上显式允许的同步读取
用户界面线程上显式允许的同步写入
启动 Realm 时自动压缩,节省文件空间
RealmConfiguration config = new RealmConfiguration.Builder() .name("alternate-realm") .allowQueriesOnUiThread(true) .allowWritesOnUiThread(true) .compactOnLaunch() .build(); Realm realm = Realm.getInstance(config); Log.v("EXAMPLE", "Successfully opened a realm at: " + realm.getPath());
val config = RealmConfiguration.Builder() .name("alternate-realm") .allowQueriesOnUiThread(true) .allowWritesOnUiThread(true) .compactOnLaunch() .build() val realm = Realm.getInstance(config) Log.v("EXAMPLE", "Successfully opened a realm at: ${realm.path}")
重要
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.") } })
打开本地 Realm
要打开 Realm,请使用 RealmConfiguration.Builder 创建 RealmConfiguration ,并将生成的 传递给RealmConfiguration
getInstance() 或 getInstanceAsync():
RealmConfiguration config = new RealmConfiguration.Builder() .allowQueriesOnUiThread(true) .allowWritesOnUiThread(true) .build(); Realm realm; try { realm = Realm.getInstance(config); Log.v("EXAMPLE", "Successfully opened a realm at: " + realm.getPath()); } catch (RealmFileException ex) { Log.v("EXAMPLE", "Error opening the realm."); Log.v("EXAMPLE", ex.toString()); }
val config = RealmConfiguration.Builder() .allowQueriesOnUiThread(true) .allowWritesOnUiThread(true) .build() var realm: Realm try { realm = Realm.getInstance(config) Log.v("EXAMPLE", "Successfully opened a realm at: ${realm.path}") } catch(ex: RealmFileException) { Log.v("EXAMPLE", "Error opening the realm.") Log.v("EXAMPLE", ex.toString()) }
只读 Realm
有时,随应用程序提供一个准备好的 Realm 文件会很有用,其中包含不经常更改的共享数据。 在配置 Realm 时,可以使用readOnly()方法将其设置为只读。 这可以防止对 Realm 的意外写入,并导致 Realm 在发生写入时抛出IllegalStateException
。
警告
只读 Realm 文件是可写的
只读域仅在进程中强制为只读。Realm 文件本身仍可写入。
RealmConfiguration config = new RealmConfiguration.Builder() .assetFile("bundled.realm") .readOnly() .modules(new BundledRealmModule()) .build();
val config = RealmConfiguration.Builder() .assetFile("readonly.realm") .readOnly() .modules(BundledRealmModule()) .build()
内存 Realms
您可以创建完全在内存中运行而不写入文件的域 。当 Android 设备上的内存不足时,内存中的 Realm 可能会 交换 暂时从主内存转移到磁盘空间。在以下情况下,SDK 会删除内存中域创建的所有文件:
Realm 关闭
所有对该领域的引用都超出了范围
要创建内存中的 Realm,请在配置域时使用inMemory():
RealmConfiguration config = new RealmConfiguration.Builder() .inMemory() .name("java.transient.realm") .build(); Realm realm = Realm.getInstance(config);
val config = RealmConfiguration.Builder() .inMemory() .name("kt.transient.realm") .build() val realm = Realm.getInstance(config)
动态域
传统 Realm 使用RealmObject
子类或RealmModel
接口定义模式。 DynamicRealm使用字符串在运行时定义模式。 打开动态 Realm 使用与传统 Realm 相同的配置,但动态 Realm 会忽略所有已配置的模式、迁移和模式版本。
动态 Realm 提供了灵活性,但牺牲了类型安全和性能。因此,只有在需要灵活性时,如迁移、手动重置客户端以及处理 CSV 文件或 JSON 等基于字符串的数据时,才使用动态 Realm。
要使用可变模式打开动态域,请使用 DynamicRealm:
RealmConfiguration config = new RealmConfiguration.Builder() .allowWritesOnUiThread(true) .allowQueriesOnUiThread(true) .name("java.dynamic.realm") .build(); DynamicRealm dynamicRealm = DynamicRealm.getInstance(config); // all objects in a DynamicRealm are DynamicRealmObjects AtomicReference<DynamicRealmObject> frog = new AtomicReference<>(); dynamicRealm.executeTransaction(transactionDynamicRealm -> { // add type Frog to the schema with name and age fields dynamicRealm.getSchema() .create("Frog") .addField("name", String.class) .addField("age", int.class); frog.set(transactionDynamicRealm.createObject("Frog")); frog.get().set("name", "Wirt Jr."); frog.get().set("age", 42); }); // access all fields in a DynamicRealm using strings String name = frog.get().getString("name"); int age = frog.get().getInt("age"); // because an underlying schema still exists, // accessing a field that does not exist throws an exception try { frog.get().getString("doesn't exist"); } catch (IllegalArgumentException e) { Log.e("EXAMPLE", "That field doesn't exist."); } // Queries still work normally RealmResults<DynamicRealmObject> frogs = dynamicRealm.where("Frog") .equalTo("name", "Wirt Jr.") .findAll();
val config = RealmConfiguration.Builder() .allowWritesOnUiThread(true) .allowQueriesOnUiThread(true) .name("kt.dynamic.realm") .build() val dynamicRealm = DynamicRealm.getInstance(config) // all objects in a DynamicRealm are DynamicRealmObjects var frog: DynamicRealmObject? = null dynamicRealm.executeTransaction { transactionDynamicRealm: DynamicRealm -> // add type Frog to the schema with name and age fields dynamicRealm.schema .create("Frog") .addField("name", String::class.java) .addField("age", Integer::class.java) frog = transactionDynamicRealm.createObject("Frog") frog?.set("name", "Wirt Jr.") frog?.set("age", 42) } // access all fields in a DynamicRealm using strings val name = frog?.getString("name") val age = frog?.getInt("age") // because an underlying schema still exists, // accessing a field that does not exist throws an exception try { frog?.getString("doesn't exist") } catch (e: IllegalArgumentException) { Log.e("EXAMPLE", "That field doesn't exist.") } // Queries still work normally val frogs = dynamicRealm.where("Frog") .equalTo("name", "Wirt Jr.") .findAll()
关闭 Realm
请务必记住在使用 Realm 实例完成后调用close()方法以释放资源。 忽视关闭 Realm 可能会导致OutOfMemoryError
。
realm.close();
realm.close()
配置要在 Realm 模式中包含的类
Realm 模块是 Realm 对象模型的集合。在打开 Realm 时指定一个或多个模块,用于控制 Realm 应在模式中包含哪些类。如果您不指定模块,则 Realm 将使用默认模块,其中包括应用程序中定义的所有 Realm 对象。
注意
所有包含 Realm 的库必须通过模块显示和使用它们的模式。这样可以防止库生成默认的 RealmModule
,从而避免该模块与任何包含该库的应用程序所使用的默认 RealmModule
发生冲突。所有使用该库的应用程序通过该模块访问库类。
// A library must create a module and set library = true. This will prevent the default // module from being created. // allClasses = true can be used instead of listing all classes in the library. public class MyLibraryModule {} // ... // Library projects are therefore required to explicitly set their own module. SyncConfiguration libraryConfig = new SyncConfiguration.Builder(app.currentUser(), LIBRARY_PARTITION) .modules(new MyLibraryModule()) .build(); // Apps can add the library RealmModule to their own schema. SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION) .modules(Realm.getDefaultModule(), new MyLibraryModule()) .build();
// A library must create a module and set library = true. This will prevent the default // module from being created. // allClasses = true can be used instead of listing all classes in the library. class MyLibraryModule // ... // Library projects are therefore required to explicitly set their own module. val libraryConfig = SyncConfiguration.Builder(app.currentUser(), LIBRARY_PARTITION) .modules(MyLibraryModule()) .build() // Apps can add the library RealmModule to their own schema. val config = SyncConfiguration.Builder(app.currentUser(), PARTITION) .modules(Realm.getDefaultModule(), MyLibraryModule()) .build()