Docs Menu
Docs Home
/ /
Kotlin SDK

Migrar del SDK de Java al SDK de Kotlin

Nota

¿Qué es el SDK de Kotlin?

El SDK de Kotlin es un nuevo SDK de cliente de Realm desarrollado íntegramente con el lenguaje de programación Kotlin. Utiliza una base de código completamente diferente a la del SDK de Java. Está diseñado específicamente para aprovechar las funciones del lenguaje Kotlin, como las corrutinas y las funciones de suspensión. El SDK de Java también es compatible con algunas de estas funciones, así como con aplicaciones de Android escritas en Kotlin. Sin embargo, el SDK de Kotlin es más propio de Kotlin que el SDK de Java.

El SDK de Java y el SDK de Kotlin difieren en muchos aspectos. En esta página, encontrará una comparación detallada de la mayoría de las diferencias entre los SDK.

El SDK de Java proporcionaba objetos, consultas y dominios activos que se actualizaban automáticamente al cambiar los datos subyacentes. El SDK de Kotlin aún proporciona esta interfaz activa en las transacciones de escritura, pero por lo demás se basa en una nueva arquitectura congelada que facilita el trabajo con objetos de dominio. Estas son algunas de las principales diferencias entre la arquitectura del SDK de Java y la del SDK de Kotlin:

  • Congelados por defecto: Todos los objetos están ahora congelados. A diferencia de los objetos activos, los objetos congelados no se actualizan automáticamente tras las escrituras en la base de datos. Aún se puede acceder a objetos activos dentro de una transacción de escritura, pero al pasar un objeto activo fuera de una transacción de escritura, se congela el objeto.

  • Seguridad de subprocesos: todas las instancias del reino, objetos, resultados de consultas y colecciones ahora se pueden transferir a través de subprocesos.

  • Singleton: ahora solo necesitas una instancia de cada reino. No es necesario abrir y cerrar reinos en hilos individuales.

Tip

El SDK de Java detecta automáticamente los modelos de objetos de dominio definidos en su aplicación y los utiliza todos en el esquema de dominios abiertos, a menos que especifique lo contrario. El SDK de Kotlin requiere que especifique manualmente los modelos de objetos de dominio que se utilizarán en el esquema de su dominio. Además:

  • El SDK de Kotlin no permite establecer ni acceder a un dominio predeterminado en la aplicación. Dado que ahora se pueden compartir dominios, objetos y resultados entre subprocesos, se puede usar un singleton global.

  • El SDK de Java usó RealmConfiguration.Builder().build() para generar instancias RealmConfiguration de. Con el SDK de Kotlin, use el método complementario RealmConfiguration.create(). RealmConfiguration

  • El SDK de Java utilizó el método estático Realm.getInstance() para abrir un realm con una configuración específica. Con el Kotlin SDK, usa el método estático Realm.open() en su lugar.

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}")

Opcionalmente, utilice RealmConfiguration.Builder para personalizar aún más su configuración:

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
)

En el SDK de Java, los modelos de objetos Realm se declaran de una de dos maneras:

  • ampliar RealmObject

  • implementar RealmModel

El SDK de Kotlin utiliza métodos predeterminados en la interfaz RealmObject. Con el SDK de Kotlin, hereda de RealmObject para declarar un modelo de objetos Realm. Las anotaciones funcionan igual que en Java para campos con propiedades especiales, como campos ignorados, claves primarias e índices.

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()
}

Tanto los SDK de Java como los de Kotlin declaran relaciones a través de campos de objeto 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
}

Con el SDK de Java, puedes definir relaciones uno a muchos con campos de tipo RealmList. El SDK de Kotlin sigue utilizando campos de tipo RealmList, pero se deben instanciar instancias de RealmList con el método complementario realmListOf().

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()
}

Con el Java SDK, era necesario usar la notación @Required para hacer que las listas de elementos primitivos no pudieran ser nulas en los modelos de objetos Realm. El SDK de Kotlin hace que las listas de elementos primitivos no sean nulos de forma predeterminada. Utiliza el operador ? para permitir que una lista de elementos primitivos sea nula.

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()
}

El SDK de Kotlin introduce nuevos nombres para los métodos que escriben en los reinos.

Con el SDK de Java, se podía escribir asincrónicamente en un dominio realm.executeTransactionAsync() con. El SDK de Kotlin utiliza la función de suspensión 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)
}

Con el Java SDK, podrías guardar de manera sincrónica en un Realm con realm.executeTransaction(). El SDK de Kotlin utiliza 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)
}

Existen varias diferencias entre las consultas en el SDK de Java y las consultas en el SDK de Kotlin:

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()

En ambos SDK, solo se pueden eliminar objetos activos. El SDK de Kotlin ofrece mutableRealm.findLatest() para acceder a una versión activa de cualquier objeto congelado. En una transacción de escritura, se pueden consultar directamente los objetos activos y eliminarlos sin findLatest() usar.

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) }
}
}

En ambos SDK, puede suscribirse para modificar las colecciones de resultados. Con el SDK de Java, puede recibir notificaciones cuando se modifiquen los resultados del dominio mediante las siguientes interfaces:

  • realmResults.addChangeListener()

  • RxJava a través de asFlowable()

  • Extensiones de Kotlin con toFlow()

El SDK de Kotlin reemplaza todas estas opciones con realmQuery.asFlow(). Una vez que se obtiene un flujo de resultados, se puede llamar a la función "collect" para suscribirse a los cambios. Cualquier objeto de tipo UpdatedResults emitido por el flujo representa un cambio en el conjunto de resultados.

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
)
}
}
}

Con el SDK de Java, los dominios, los objetos Realm y los resultados no se pueden transferir entre subprocesos. El SDK de Kotlin congela estos objetos por defecto, haciéndolos seguros para subprocesos. A diferencia de los objetos activos que utiliza el SDK de Java, los objetos congelados del SDK de Kotlin no se actualizan automáticamente cuando cambian los datos subyacentes. Con el SDK de Kotlin, debe usar notificaciones para suscribirse a las actualizaciones.

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()

Con el SDK de Java, las migraciones eran un proceso manual. El SDK de Kotlin automatiza las migraciones, pero también ofrece acceso a una interfaz dinámica similar para realizar ajustes personalizados en la lógica de migración.

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)

Ahora que comprende las diferencias entre el SDK de Java y el SDK de Kotlin, consulte el resto de la documentación del SDK de Kotlin.

Volver

Telemetría del SDK

En esta página