Docs Menu
Docs Home
/ /
Atlas Device SDK
/

Java SDK から Kotlin SDK への移行

項目一覧

  • Overview
  • Kotlin SDK アーキテクチャ
  • Realm の起動
  • Realm オブジェクトモデル
  • 関係
  • 1 対 1
  • 1 対多
  • スキーマ タイプ
  • 書込み (write)
  • 非同期
  • 同期
  • クエリ
  • フィルター
  • ソート、個別、制限
  • 削除
  • notifications
  • スレッド化
  • 移行
  • 次は?

注意

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 を開いて閉じる必要はありません。

Tip

以下も参照してください。

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を使用して構成をさらにカスタマイズします。

Kotlin SDK
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
)

Tip

以下も参照してください。

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
// no support for chars: no charField
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;
// no support for chars: no charField
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()
}

Tip

以下も参照してください。

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 {
// this: MutableRealm
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 {
// this: MutableRealm
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()
// delete one object synchronously
realm.executeTransaction {
transactionRealm: Realm? ->
sample!!.deleteFromRealm()
}
// delete a query result asynchronously
realm.executeTransactionAsync {
backgroundRealm: Realm ->
backgroundRealm.where(
Sample::class.java
).findFirst()!!.deleteFromRealm()
}
Sample sample =
realm.where(Sample.class)
.findFirst();
// delete one object synchronously
realm.executeTransaction(
transactionRealm ->
sample.deleteFromRealm());
// delete a query result asynchronously
realm.executeTransactionAsync(
backgroundRealm ->
backgroundRealm
.where(Sample.class)
.findFirst()
.deleteFromRealm());
val sample: Sample? =
realm.query<Sample>()
.first().find()
// delete one object synchronously
realm.writeBlocking {
if (sample != null) {
findLatest(sample)
?.also { delete(it) }
}
}
// delete a query result asynchronously
GlobalScope.launch {
realm.write {
query<Sample>()
.first()
.find()
?.also { delete(it) }
}
}

どちらの SDK でも、結果のコレクションに対する変更をサブスクライブできます。 Java SDK を使用すると、Realm の結果が次のインターフェースで変更されるたびに通知を受け取ることができました。

  • realmResults.addChangeListener()

  • RxJava による asFlowable()

  • Kotlin 拡張機能 toFlow()

Kotlin SDK は、これらのオプションをすべてRealmQuery.asFlow()に置き換えます。 結果のフローができたら、 コレクション を呼び出すことができます 変更をサブスクライブする 。フローによって出力されるタイプUpdatedResultsのオブジェクトは、結果セットへの変更を表します。

realm.where(Sample::class.java)
.findAllAsync()
.addChangeListener {
samples: RealmResults<Sample>?,
changeSet: OrderedCollectionChangeSet ->
// log change description
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 change description
Log.v("EXAMPLE",
"Results changed. " +
"change ranges: " +
Arrays.toString(
changeSet
.getChangeRanges()) +
", insertion ranges: " +
Arrays.toString(
changeSet
.getInsertionRanges()) +
", deletion ranges: " +
Arrays.toString(
changeSet
.getDeletionRanges()));
});
// in a coroutine or a suspend function
realm.query<Sample>().asFlow().collect {
results: ResultsChange<Sample> ->
when (results) {
is InitialResults<Sample> -> {
// do nothing with the
// initial set of results
}
is UpdatedResults<Sample> -> {
// log change description
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()
// save sample field in a
// separate variable
// for access on another thread
val sampleStringField =
sample!!.stringField
val executorService =
Executors.newFixedThreadPool(4)
executorService.execute {
// cannot pass a realm
// into another thread,
// so get a new instance
// for separate thread
val threadRealm =
Realm.getInstance(config)
// cannot access original
// sample on another
// thread, use
// sampleStringField instead
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();
// save sample field in a variable
// for access on another thread
String sampleStringField =
sample.stringField;
ExecutorService executorService =
Executors.newFixedThreadPool(4);
executorService.execute(() -> {
// cannot pass a realm
// into another thread,
// so get a new instance
// for separate thread
Realm threadRealm =
Realm.getInstance(config);
// cannot access original
// sample on another
// thread, use
// sampleStringField instead
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) {
// can access the realm opened on
// a different thread
realm.query<Sample>().find()
// can access realm object queried
// on a different thread
Log.v(sample!!.stringField)
}.join()

Tip

以下も参照してください。

Java SDK では、移行は手動プロセスでした。 Kotlin SDK は移行を自動化しますが、移行ロジックをカスタム調整するための同様の 動的 Realm インターフェースにもアクセスできます。

val config =
RealmConfiguration.Builder()
.migration { realm: DynamicRealm,
oldVersion: Long,
newVersion: Long ->
val schema: RealmSchema =
realm.schema
if (oldVersion == 0L) {
// perform schema migration
schema.get("Sample")
?.addField(
"new_field",
String::class.java
)
}
// migrate data
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) {
// perform schema migration
schema.get("Sample")
.addField("new_field",
String.class);
}
// migrate data
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());
// A Realm migration that performs
// automatic schema migration
// and allows additional custom
// migration of data.
RealmConfiguration.Builder(
schema = setOf(Sample::class))
.migration(AutomaticSchemaMigration {
context:
AutomaticSchemaMigration.MigrationContext ->
val oldRealm:
DynamicRealm =
context.oldRealm
val newRealm:
DynamicMutableRealm =
context.newRealm
// dynamic realm gives access
// to realm data
// through a generic string
// based API
context.enumerate("Sample") {
oldObject:
DynamicRealmObject,
newObject:
DynamicMutableRealmObject? ->
newObject?.set("longField",
42L)
}
})
.build()
val realm = Realm.open(config)

Java SDK と Kotlin SDK の違いが理解できたので、 Kotlin SDK ドキュメントの残りの部分を確認してください。

戻る

SDK テレメトリ