Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/

Migrar do Java SDK para o Kotlin SDK

Nesta página

  • Visão geral
  • Arquitetura do Kotlin SDK
  • Abrindo realms
  • Realm Object Models
  • Relacionamentos
  • Um a um
  • Um-para-Muitos
  • Tipos de esquema
  • Escreve
  • Async
  • sincronizar
  • Consultas
  • Filtros
  • Classificar, Distinto, Limite
  • Exclui
  • Notificações
  • Segmentação
  • Migrações
  • E agora?

Observação

O que é o Kotlin SDK?

O Kotlin SDK é um novo SDK do cliente Realm criado inteiramente com a linguagem de programação Kotlin. O Kotlin SDK usa uma base de código totalmente diferente do Java SDK. Ele foi projetado especificamente para aproveitar os recursos da linguagem Kotlin, como corrotinas e funções de suspensão. O Java SDK também oferece suporte a alguns desses recursos, bem como a aplicativos Android escritos no Kotlin. Mas o Kotlin SDK é mais automático do que o Java SDK.

O Java SDK e o Kotlin SDK diferem de várias maneiras. Nesta página, você encontrará uma comparação de alto nível da maioria das maneiras que os SDKs diferem.

O Java SDK forneceu objetos ao vivo, queries e domínios que são atualizados automaticamente quando os dados subjacentes são alterados. O SDK Kotlin ainda fornece essa interface ao vivo em transações de escrita, mas depende de uma nova arquitetura congelada que torna os objetos do Realm mais fáceis de trabalhar. Aqui estão algumas das principais diferenças entre a arquitetura Java SDK e a arquitetura Kotlin SDK:

  • Frozen by default (Frozen por padrão): todos os objetos estão congelados. Ao contrário dos objetos ativos, os objetos congelados não são atualizados automaticamente depois que o banco de dados é gravado. Você ainda pode acessar objetos dinâmicos em uma transação de gravação, mas passar um objeto dinâmico para fora de uma transação de gravação congela o objeto.

  • Segurança de thread: Todas as instâncias de Realm, objetos de Realm, resultados de queries e coleções agora podem ser transferidos entre threads.

  • Singleton: Agora você só precisa de uma instância de cada Realm. Não há necessidade de abrir e fechar domínios em threads individuais.

Dica

Veja também:

O SDK Java detecta automaticamente os modelos de objetos de Realm definidos em sua aplicação e usa todos eles no esquema de regiões abertas, a menos que você especifique o contrário. O SDK Kotlin exige que você especifique manualmente os modelos de objetos de Realm a serem usados em seu esquema de Realm. Além disso:

  • O Kotlin SDK não oferece a capacidade de definir e acessar um domínio padrão em seu aplicativo. Como agora você pode compartilhar realms, objetos e resultados entre threads, você pode confiar em um singleton global.

  • O Java SDK usou RealmConfiguration.Builder().build() para gerar instâncias de RealmConfiguration. Com o Kotlin SDK, use RealmConfiguration.create() método complementar RealmConfiguration .

  • O SDK Java utilizou o método estático Realm.getInstance() para abrir um domínio com uma determinada configuração. Com o Kotlin SDK, use o método Realm.open() estático.

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, utilize RealmConfiguration.Builder para personalizar sua configuração ainda mais:

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

Dica

Veja também:

No Java SDK, você declara modelos de objeto do Realm de duas maneiras:

  • ampliar RealmObject

  • implementar RealmModel

O Kotlin SDK usa métodos padrão na interface RealmObject . Com o Kotlin SDK, herde de RealmObject para declarar um modelo de objeto Realm. As anotações funcionam da mesma forma que em java para campos com propriedades especiais, como campos ignorados, chaves primárias 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()
}

Os SDKs Java e Kotlin declaram relação por meio dos campos de objeto de 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
}

Com o SDK Java, você pode definir relações um-para-muitos com campos do tipo RealmList. O Kotlin SDK ainda usa campos do tipo RealmList, mas você deve instanciar instâncias RealmList com o método complementar 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()
}

Com o Java SDK, você precisava usar a anotação do @Required para fazer listas de primitivos não anuláveis em modelos de objeto de domínio. O Kotlin SDK faz listas de primitivos não anuláveis por padrão. Use o operador ? para fazer uma lista de primitivos anuláveis.

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

O Kotlin SDK introduz novos nomes para os métodos que escrevem em domínios.

Com o Java SDK, você pode gravar de forma assíncrona em um realm com realm.executeTransactionAsync(). O Kotlin SDK usa a função suspender realm.write() no lugar.

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

Com o Java SDK, você pode gravar de forma sincronizada em um realm com realm.executeTransaction(). O Kotlin SDK usa 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)
}

Existem várias diferenças entre as queries no Java SDK e as queries no Kotlin SDK:

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

Em ambos os SDKs, você só pode excluir objetos ao vivo. O Kotlin SDK fornece mutableRealm.findLatest() para acessar uma versão ativa de qualquer objeto congelado. Em uma transação por escrito, você pode consultar diretamente objetos ao vivo e excluí-los sem usar o 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) }
}
}

Em ambos os SDKs, você pode se inscrever para alterar as coleções de resultados. Com o Java SDK, você pode receber notificações sempre que os resultados do domínio forem alterados com as seguintes interfaces:

  • realmResults.addChangeListener()

  • RxJava por meio de asFlowable()

  • Extensões de Kotlin com toFlow()

O Kotlin SDK substitui todas essas opções por realmQuery.asFlow(). Depois de ter um fluxo de resultados, você pode chamar a coleta para assinar as alterações. Qualquer objeto do tipo UpdatedResults emitido pelo fluxo representa uma alteração no 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
)
}
}
}

Com o Java SDK, os domínios, os objetos do Realm e os resultados não podem ser passados entre threads. O Kotlin SDK congela esses objetos por padrão, tornando-os seguros contra threads. Ao contrário dos objetos dinâmicos usados pelo SDK Java, os objetos congelados encontrados no SDK Kotlin não são atualizados automaticamente quando os dados subjacentes são alterados. Com o Kotlin SDK, você deve usar notificações para assinar atualizações.

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

Dica

Veja também:

Com o Java SDK, migrações foram um processo manual. O SDK Kotlin automatiza as migrações, mas também oferece acesso a uma interface dinâmica semelhante para ajustes personalizados na lógica de migração.

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)

Agora que você entende as diferenças entre SDK Java e Kotlin SDK, confira o restante da documentação do Kotlin SDK.

Voltar

Telemetria SDK