Atlas Device SDK は非推奨です。 詳細については、 の
廃止ページを参照してください。
注意
Kotlin SDKとは
Kotlin SDK は、 Kotlin プログラミング言語で完全に構築された新しい Realm クライアント SDK です。 Kotlin SDK は、Java SDK とは完全に異なるコードベースを使用します。 コルーチンや一時停止関数などの Kotlin 言語の機能を活用するように特別に設計されています。 Java SDKは、これらの機能の一部と、 Kotlin で記述された Android アプリケーションもサポートしています。 ただし、 Kotlin SDKは Java SDK よりも Kotlin 慣用的です。
Java SDK と Kotlin SDK は多くの点で異なります。 このページでは、SDK が異なる方法のほとんどを高レベルで比較します。
Java SDK は、基礎となるデータが変更されたときに自動的に更新されるライブ オブジェクト、クエリ、Realm を提供します。 Kotlin SDK は引き続き書込みトランザクションでこのライブ インターフェースを提供しますが、それ以外の場合は Realm オブジェクトの操作を容易にする新しい固定アーキテクチャに依存しています。 Java SDK アーキテクチャと Kotlin SDK アーキテクチャの主な違いをいくつか示します。
デフォルトで固定: すべてのオブジェクトが固定されます。 ライブオブジェクトとは異なり、固定オブジェクトはデータベースが書き込まれた後に自動的に更新されることはありません。 書き込みトランザクション内でライブオブジェクトにアクセスすることはできますが、書き込みトランザクションからライブオブジェクトを渡すと、オブジェクトはフリーズします。
スレッドセーフ性: すべての Realm インスタンス、オブジェクト、クエリ結果、コレクションをスレッド間で転送できるようになりました。
シングルオン: 各 Realm の インスタンスが 1 つだけになりました。 個々のスレッドで Realm を開いて閉じる必要はありません。
Java SDK は、アプリケーションで定義された Realm オブジェクトモデルを自動的に検出し、特に指定されていない限り、開かれた Realm のスキーマでそれらをすべて使用します。 Kotlin SDK では、Realm スキーマで使用する Realm オブジェクトモデルを手動で指定する必要があります。 さらに、
Kotlin SDK では、アプリケーション内のデフォルトの Realm を設定してアクセスする機能は提供されません。 Realm、オブジェクト、結果をスレッド間で共有できるようになったため、代わりにグローバル 単一ドキュメントに依存できます。
Java SDK はRealmConfiguration.Builder().build()
を使用してRealmConfiguration
のインスタンスを生成しました。 Kotlin SDK では、 RealmConfiguration.create() 代わりに、コンフィギュレーション メソッドRealmConfiguration
を使用します。
Java SDK は静的Realm.getInstance()
メソッドを使用して、指定された構成で Realm を開きます。 Kotlin SDK では、代わりに静的Realm.open()
メソッドを使用してください。
val config = RealmConfiguration.Builder() | .build() | var realm: Realm | realm = Realm.getInstance(config) | Log.v( | "EXAMPLE", | "Successfully opened a realm: " | + realm.path | ) |
RealmConfiguration config = | new RealmConfiguration.Builder() | .build(); | | Realm realm; | realm = Realm.getInstance(config); | Log.v("EXAMPLE", | "Successfully opened a realm: " | + realm.getPath()); |
| val config = RealmConfiguration.create( | setOf(Frog::class, Sample::class)) | val realm = Realm.open(config) | Log.v("Successfully opened realm:" + | "${realm.configuration.name}") |
|
オプションで、 RealmConfiguration.Builderを使用して構成をさらにカスタマイズします。
val config = RealmConfiguration.Builder( |
setOf(Frog::class, Sample::class)) |
.name(REALM_NAME) |
.deleteRealmIfMigrationNeeded() |
.directory(PATH) |
.encryptionKey(KEY) |
.build() |
val realm = Realm.open(config) |
Log.v("Successfully opened realm:" + |
realm.configuration.name |
) |
Java SDK では、次の 2 つの方法のいずれかの方法で Realm オブジェクトモデルを宣言します。
拡張 RealmObject
を実装する RealmModel
Kotlin SDK は代わりに、 RealmObject
インターフェースのデフォルト メソッドを使用します。 Kotlin SDK では、 RealmObject
から継承して Realm オブジェクトモデルを宣言します。 注釈は、無視されるフィールド、プライマリキー、インデックスなどの特殊なプロパティを持つフィールドに対して、 Javaと同じ方法で機能します。
open class Sample : RealmObject() { | @PrimaryKey | var stringField = "Realm" | var byteField: Byte = 0xA | | var shortField: Short = 17 | var intField = 42 | @Index | var longField = 256L | var booleanField = true | var floatField = 3.14f | var doubleField = 1.19840122 | var timestampField = Date() | } |
public class Sample extends RealmObject { | @PrimaryKey | public String stringField = "Realm"; | public Byte byteField = 0xA; | | public Short shortField = 17; | public Integer intField = 42; | @Index | public Long longField = 256L; | public Boolean booleanField = true; | public Float floatField = 3.14f; | public Double doubleField = | 1.19840122; | public Date timestampField = | new Date(); | } |
| class Sample : RealmObject { | @PrimaryKey | var stringField: String = "Realm" | var byteField: Byte = 0xA | var charField: Char = 'a' | var shortField: Short = 17 | var intField: Int = 42 | @Index | var longField: Long = 256L | var booleanField: Boolean = true | var floatField: Float = 3.14f | var doubleField: Double = 1.19840122 | var timestampField: RealmInstant = | RealmInstant.from( | 100, | 1000) | var objectIdField: ObjectId = ObjectId() | } |
|
Java と Kotlin SDK はどちらも Realm オブジェクト フィールドを通じて関係を宣言します。
open class Child : RealmObject() { | var frog: Frog? = null | } |
public class Child | extends RealmObject { | public Frog frog = null; | } |
| class Child : RealmObject { | var frog: Frog? = null | } |
|
Java SDK を使用すると、 RealmList
型のフィールドとの 1 対多の関係を定義できます。 Kotlin SDK は引き続きRealmList
型のフィールドを使用しますが、 RealmListOf() コンフィギュレーションメソッドを使用してRealmList
インスタンスをインスタンス化する必要があります。
open class Kid : RealmObject() { | var frogs = RealmList<Frog>() | } |
public class Kid | extends RealmObject { | public RealmList<Frog> frogs = | new RealmList<Frog>(); | } |
| class Kid : RealmObject { | var frogs: RealmList<Frog> = | realmListOf() | } |
|
Java SDK では、Realm オブジェクトモデルで null 以外のプリミティブのリストを作成するには、 @Required
アノテーションを使用する必要がありました。 Kotlin SDK は、デフォルトで null 以外のプリミティブのリストを作成します。 プリミティブのリストを null 可能にするには、 ?
演算子を使用します。
open class CollegeStudent : RealmObject() { | @Required | var notes = RealmList<String>() | var nullableNotes = RealmList<String>() | } |
public class CollegeStudent | extends RealmObject { | @Required | public RealmList<String> notes = | new RealmList<String>(); | public RealmList<String> nullableNotes = | new RealmList<String>(); | } |
| class Student : RealmObject { | var notes: RealmList<String> = | realmListOf() | var nullableNotes: RealmList<String?> = | realmListOf() | } |
|
Kotlin SDK では、Realm に書込むメソッドの新しい名前が導入されています。
Java SDK を使用すると、 realm.executeTransactionAsync()
を使用して Realm に非同期に書込み (write) が可能です。 Kotlin SDK は一時停止関数Realm.write()を使用します ください。
realm.executeTransactionAsync { | transactionRealm: Realm -> | val sample: Sample = | Sample() | sample.stringField = "Sven" | transactionRealm.copyToRealm( | sample | ) | } |
realm.executeTransactionAsync( | transactionRealm -> { | Sample sample = new Sample(); | sample.stringField = "Sven"; | transactionRealm.copyToRealm(sample); | }); |
| realm.write { | | val sample = Sample() | sample.stringField = "Sven" | this.copyToRealm(sample) | } |
|
Java SDK を使用すると、 realm.executeTransaction()
を使用して Realm に同期的に書込み (write) が可能です。 Kotlin SDK はRealm.writeBlocking()を使用します。
realm.executeTransaction { | transactionRealm: Realm -> | val sample: Sample = | Sample() | sample.stringField = "Sven" | transactionRealm.copyToRealm( | sample | ) | } |
realm.executeTransaction( | transactionRealm -> { | Sample sample = new Sample(); | sample.stringField = "Sven"; | transactionRealm.copyToRealm(sample); | }); |
| realm.writeBlocking { | | val sample = Sample() | sample.stringField = "Sven" | this.copyToRealm(sample) | } |
|
Java SDK のクエリと Kotlin SDK のクエリにはいくつかの違いがあります。
Java SDKでは、fluent インターフェースまたはRQL ( RQL )を使用して、Realm 内のオブジェクトをクエリできます。 Kotlin SDK は RQL のみを使用します。
Java SDK はrealm.where()
を使用して Realm をクエリしますが、 Kotlin SDK はRealm.query() を使用します。
Java SDKでは、realmQuery.findAllAsync()
とrealmQuery.findFirstAsync()
を使用して非同期にクエリを実行できます。 Kotlin SDKでは、 RealmQuery.asFlow() を使用して非同期にクエリを実行します。結果のフローができたら 、 を 収集 できます 結果。
Java SDK を使用すると、 realmQuery.findAll()
とrealmQuery.findFirst()
を使用して同期的にクエリを実行できます。 Kotlin SDK では、 RealmQuery.find() を使用して同期クエリを実行します。
val samples = | realm.where( | Sample::class.java | ).findAll() | val samplesThatBeginWithN = | realm.where( | Sample::class.java | ) | .beginsWith( | "stringField", | "N" | ).findAll() |
RealmResults<Sample> samples = | realm | .where(Sample.class) | .findAll(); | | RealmResults<Sample> samplesThatBeginWithN = | realm | .where(Sample.class) | .beginsWith("stringField", | "N") | .findAll(); |
| val samples: RealmResults<Sample> = | realm.query<Sample>().find() | | val samplesThatBeginWithN: | RealmResults<Sample> = | realm.query<Sample>( | "stringField BEGINSWITH 'N'" | ).find() |
|
val aggregates = | realm.where( | Sample::class.java | ) | .distinct("stringField") | .sort( | "stringField", | Sort.ASCENDING | ) | .limit(2) | .findAll() |
RealmResults<Sample> aggregates = | realm.where(Sample.class) | .distinct("stringField") | .sort("stringField", | Sort.ASCENDING) | .limit(2) | .findAll(); |
| val aggregates: RealmResults<Sample> = | realm.query<Sample>() | .distinct(Sample::stringField.name) | .sort(Sample::stringField.name, | Sort.ASCENDING) | .limit(2) | .find() |
|
どちらの SDKでも、削除できるのはライブ オブジェクトのみです。 Kotlin SDK はMutableRealm.findLargest()を提供します 固定されたオブジェクトのライブ バージョンにアクセスします。 書込みトランザクションでは、 findLatest()
を使用せずにライブ オブジェクトを直接クエリして削除できます。
val sample = | realm.where( | Sample::class.java | ).findFirst() | | | realm.executeTransaction { | transactionRealm: Realm? -> | sample!!.deleteFromRealm() | } | | | realm.executeTransactionAsync { | backgroundRealm: Realm -> | backgroundRealm.where( | Sample::class.java | ).findFirst()!!.deleteFromRealm() | } |
Sample sample = | realm.where(Sample.class) | .findFirst(); | | | realm.executeTransaction( | transactionRealm -> | sample.deleteFromRealm()); | | | realm.executeTransactionAsync( | backgroundRealm -> | backgroundRealm | .where(Sample.class) | .findFirst() | .deleteFromRealm()); |
| val sample: Sample? = | realm.query<Sample>() | .first().find() | | | realm.writeBlocking { | if (sample != null) { | findLatest(sample) | ?.also { delete(it) } | } | } | | | GlobalScope.launch { | realm.write { | query<Sample>() | .first() | .find() | ?.also { delete(it) } | } | } |
|
どちらの SDK でも、結果のコレクションに対する変更をサブスクライブできます。 Java SDK を使用すると、Realm の結果が次のインターフェースで変更されるたびに通知を受け取ることができました。
Kotlin SDK は、これらのオプションをすべてRealmQuery.asFlow()に置き換えます。 結果のフローができたら、 コレクション を呼び出すことができます 変更をサブスクライブする 。フローによって出力されるタイプUpdatedResults
のオブジェクトは、結果セットへの変更を表します。
realm.where(Sample::class.java) | .findAllAsync() | .addChangeListener { | samples: RealmResults<Sample>?, | changeSet: OrderedCollectionChangeSet -> | | Log.v( | "EXAMPLE", | ("Results changed. " + | "change ranges: " + | Arrays.toString( | changeSet | .changeRanges | ) + | ", insertion ranges: " + | Arrays.toString( | changeSet | .insertionRanges | ) + | ", deletion ranges: " + | Arrays.toString( | changeSet | .deletionRanges | )) | ) | } |
realm.where(Sample.class).findAllAsync() | .addChangeListener( | (samples, changeSet) -> { | | Log.v("EXAMPLE", | "Results changed. " + | "change ranges: " + | Arrays.toString( | changeSet | .getChangeRanges()) + | ", insertion ranges: " + | Arrays.toString( | changeSet | .getInsertionRanges()) + | ", deletion ranges: " + | Arrays.toString( | changeSet | .getDeletionRanges())); | }); |
| | realm.query<Sample>().asFlow().collect { | results: ResultsChange<Sample> -> | when (results) { | is InitialResults<Sample> -> { | | | } | is UpdatedResults<Sample> -> { | | Log.v("Results changed. " + | "change ranges: " + | results.changeRanges + | ", insertion ranges: " + | results.insertionRanges + | ", deletion ranges: " + | results.deletionRanges | ) | } | } | } |
|
Java SDK では、Realm、Realm オブジェクト、および結果をスレッド間で渡すことはできません。 Kotlin SDK はこれらのオブジェクトをデフォルトでフリーズし、スレッドセーフにします。 Java SDK で使用されるライブ オブジェクトとは異なり、 Kotlin SDK にある固定オブジェクトは、基礎となるデータが変更されても自動的に更新されません。 Kotlin SDK では、代わりに通知を使用して更新をサブスクライブする必要があります。
realm = Realm.getInstance(config) | val sample = | realm.where( | Sample::class.java | ).findFirst() | | | | val sampleStringField = | sample!!.stringField | val executorService = | Executors.newFixedThreadPool(4) | executorService.execute { | | | | | val threadRealm = | Realm.getInstance(config) | | | | | val threadSample = | threadRealm.where( | Sample::class.java | ) | .equalTo( | "stringField", | sampleStringField | ).findFirst() | Log.v( | "EXAMPLE", | "Separate thread sample: " + | threadSample | ) | } |
realm = Realm.getInstance(config); | Sample sample = realm | .where(Sample.class).findFirst(); | | | String sampleStringField = | sample.stringField; | ExecutorService executorService = | Executors.newFixedThreadPool(4); | executorService.execute(() -> { | | | | | Realm threadRealm = | Realm.getInstance(config); | | | | | Sample threadSample = | threadRealm | .where(Sample.class) | .equalTo("stringField", | sampleStringField) | .findFirst(); | Log.v("EXAMPLE", | "Separate thread sample: " | + threadSample); | }); |
| val realm = Realm.open(config) | val sample: Sample? = | realm.query<Sample>() | .first() | .find() | | launch(Dispatchers.Unconfined) { | | | realm.query<Sample>().find() | | | Log.v(sample!!.stringField) | }.join() |
|
Java SDK では、移行は手動プロセスでした。 Kotlin SDK は移行を自動化しますが、移行ロジックをカスタム調整するための同様の 動的 Realm インターフェースにもアクセスできます。
val config = | RealmConfiguration.Builder() | .migration { realm: DynamicRealm, | oldVersion: Long, | newVersion: Long -> | val schema: RealmSchema = | realm.schema | if (oldVersion == 0L) { | | schema.get("Sample") | ?.addField( | "new_field", | String::class.java | ) | } | | | schema.get("Sample") | ?.transform { | obj: DynamicRealmObject -> | obj.set( | "longField", | 42L | ) | } | }.build() | val realm: Realm = | Realm.getInstance(config) | Log.v( | "EXAMPLE", | "Successfully opened a realm: " | + realm.path | ) |
RealmConfiguration config = | new RealmConfiguration.Builder() | .migration((realm, | oldVersion, | newVersion) -> { | RealmSchema schema = | realm.getSchema(); | | if (oldVersion == 0L) { | | schema.get("Sample") | .addField("new_field", | String.class); | } | | | schema.get("Sample") | .transform(obj -> | obj.set("longField", | 42L)); | }).build(); | | Realm realm; | realm = Realm.getInstance(config); | Log.v("EXAMPLE", | "Successfully opened a realm: " | + realm.getPath()); |
| | | | | RealmConfiguration.Builder( | schema = setOf(Sample::class)) | .migration(AutomaticSchemaMigration { | context: | AutomaticSchemaMigration.MigrationContext -> | val oldRealm: | DynamicRealm = | context.oldRealm | val newRealm: | DynamicMutableRealm = | context.newRealm | | | | | context.enumerate("Sample") { | oldObject: | DynamicRealmObject, | newObject: | DynamicMutableRealmObject? -> | newObject?.set("longField", | 42L) | } | }) | .build() | val realm = Realm.open(config) |
|