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

Início rápido - Java SDK

Nesta página

  • Inicializar Realm
  • Definir seu modelo de objeto
  • Abrir um Realm
  • Criar, ler, atualizar e excluir objetos
  • Fique atento às mudanças
  • Exemplo completo
  • Saída

Dica

Este guia não usa o Device Sync

Este guia pode ajudá-lo a começar a usar o Realm local do dispositivo. Se seu aplicação precisar se comunicar com um aplicativo de backend pela rede usando recursos como Atlas Device Sync, Realm Functions ou gerenciamento de usuários, siga o guia Iniciar Rápido com Sincronização .

Esta página contém informações para integrar o Realm à sua aplicação rapidamente. Antes de começar, verifique se tem:

  • Instalou o Java SDK

Antes de usar o Realm em seu aplicativo, você deve inicializar a biblioteca do Realm. Seu aplicativo deve inicializar o Realm apenas uma vez a cada vez que o aplicativo for executado.

Para inicializar a biblioteca Realm , forneça um Android context para a função estática Realm.init() . Você pode fornecer uma Atividade, Fragmento ou Aplicativo context para inicialização sem nenhuma diferença no comportamento. Você pode inicializar a biblioteca Realm no onCreate() método de uma subclasse de aplicação para garantir que você inicialize o Realm apenas uma vez a cada vez que o aplicação for executado.

Realm.init(this); // context, usually an Activity or Application
Realm.init(this) // context, usually an Activity or Application

Dica

Registre sua subclasse de aplicativo no manifesto do Android

Se você criar sua própria subclasse Application , deverá adicioná-la ao AndroidManifest.xml do seu aplicativo para executar sua lógica personalizada do aplicativo. Defina a propriedade android.name da definição do aplicativo do seu manifesto para garantir que o Android instancie sua subclasse Application antes de qualquer outra classe quando um usuário iniciar seu aplicativo.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mongodb.example">
<application
android:name=".MyApplicationSubclass"
...
/>
</manifest>

O modelo de dados do aplicativo define a estrutura de dados armazenados no Realm. Você pode definir o modelo de dados do seu aplicativo por meio de classes Kotlin ou Java no código do aplicação com Realm Object Models.

Para definir o modelo de dados do aplicativo, adicione as seguintes definições de classe ao código do aplicação :

Task.java
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.Required;
public class Task extends RealmObject {
@PrimaryKey private String name;
@Required private String status = TaskStatus.Open.name();
public void setStatus(TaskStatus status) { this.status = status.name(); }
public String getStatus() { return this.status; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Task(String _name) { this.name = _name; }
public Task() {}
}
TaskStatus.java
public enum TaskStatus {
Open("Open"),
InProgress("In Progress"),
Complete("Complete");
String displayName;
TaskStatus(String displayName) {
this.displayName = displayName;
}
}
Task.kt
enum class TaskStatus(val displayName: String) {
Open("Open"),
InProgress("In Progress"),
Complete("Complete"),
}
open class Task() : RealmObject() {
@PrimaryKey
var name: String = "task"
@Required
var status: String = TaskStatus.Open.name
var statusEnum: TaskStatus
get() {
// because status is actually a String and another client could assign an invalid value,
// default the status to "Open" if the status is unreadable
return try {
TaskStatus.valueOf(status)
} catch (e: IllegalArgumentException) {
TaskStatus.Open
}
}
set(value) { status = value.name }
}

Use RealmConfiguration para controlar as especificidades do Realm que você gostaria de abrir, incluindo o nome ou a localização do Realm, se deve permitir leituras ou gravações síncronas em um Realm no thread da interface do usuário e muito mais.

String realmName = "My Project";
RealmConfiguration config = new RealmConfiguration.Builder().name(realmName).build();
Realm backgroundThreadRealm = Realm.getInstance(config);
val realmName: String = "My Project"
val config = RealmConfiguration.Builder().name(realmName).build()
val backgroundThreadRealm : Realm = Realm.getInstance(config)

Depois de abrir um Realm, você pode modificar os objetos dentro desse Realm em um bloco de transação de gravação .

Importante

Leituras e gravações síncronas na thread da interface do usuário

Por padrão, você só pode ler ou escrever em um realm no thread da UI do aplicativo usando transações assíncronas. Ou seja, você só pode usar métodos Realm cujo nome termina com a palavra Async no thread principal do seu aplicativo Android, a menos que você permita explicitamente o uso de métodos síncronos.

Essa restrição existe para o benefício dos usuários do aplicativo: executar operações de leitura e escrita no thread da interface do usuário pode levar a interações de interface do usuário não responsivas ou lentas, portanto, geralmente é melhor lidar com essas operações de forma assíncrona ou em um thread de fundo. No entanto, se o seu aplicativo exigir o uso de leituras ou gravações síncronas de realm no thread da interface do usuário, você poderá permitir explicitamente o uso de métodos síncronos com as seguintes opções SyncConfiguration:

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
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.")
}
})

Para criar um novo Task, instancie uma instância da classe Task e adicione-a ao domínio em um bloco de gravação:

Task Task = new Task("New Task");
backgroundThreadRealm.executeTransaction (transactionRealm -> {
transactionRealm.insert(Task);
});
val task : Task = Task()
task.name = "New Task"
backgroundThreadRealm.executeTransaction { transactionRealm ->
transactionRealm.insert(task)
}

Você pode recuperar uma coleção ativa de todos os itens no Realm:

// all Tasks in the realm
RealmResults<Task> Tasks = backgroundThreadRealm.where(Task.class).findAll();
// all tasks in the realm
val tasks : RealmResults<Task> = backgroundThreadRealm.where<Task>().findAll()

Você também pode filtrar essa coleção usando um filtro:

// you can also filter a collection
RealmResults<Task> TasksThatBeginWithN = Tasks.where().beginsWith("name", "N").findAll();
RealmResults<Task> openTasks = Tasks.where().equalTo("status", TaskStatus.Open.name()).findAll();
// you can also filter a collection
val tasksThatBeginWithN : List<Task> = tasks.where().beginsWith("name", "N").findAll()
val openTasks : List<Task> = tasks.where().equalTo("status", TaskStatus.Open.name).findAll()

Para modificar uma tarefa, atualize suas propriedades em um bloco de transação de escrita:

Task otherTask = Tasks.get(0);
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction( transactionRealm -> {
Task innerOtherTask = transactionRealm.where(Task.class).equalTo("_id", otherTask.getName()).findFirst();
innerOtherTask.setStatus(TaskStatus.Complete);
});
val otherTask: Task = tasks[0]!!
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction { transactionRealm ->
val innerOtherTask : Task = transactionRealm.where<Task>().equalTo("name", otherTask.name).findFirst()!!
innerOtherTask.status = TaskStatus.Complete.name
}

Por fim, você pode excluir uma tarefa chamando o método deleteFromRealm() em um bloco de transação de gravação :

Task yetAnotherTask = Tasks.get(0);
String yetAnotherTaskName = yetAnotherTask.getName();
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction( transactionRealm -> {
Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo("_id", yetAnotherTaskName).findFirst();
innerYetAnotherTask.deleteFromRealm();
});
val yetAnotherTask: Task = tasks.get(0)!!
val yetAnotherTaskName: String = yetAnotherTask.name
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction { transactionRealm ->
val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo("name", yetAnotherTaskName).findFirst()!!
innerYetAnotherTask.deleteFromRealm()
}

Você pode assistir a um Realm, coleção ou objeto para alterações anexando um OrderedRealmCollectionChangeListener personalizado com o método addChangeListener() :

// all Tasks in the realm
RealmResults<Task> Tasks = uiThreadRealm.where(Task.class).findAllAsync();
Tasks.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Task>>() {
@Override
public void onChange(RealmResults<Task> collection, OrderedCollectionChangeSet changeSet) {
// process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate
OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges();
for (OrderedCollectionChangeSet.Range range : deletions) {
Log.v("QUICKSTART", "Deleted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1));
}
OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges();
for (OrderedCollectionChangeSet.Range range : insertions) {
Log.v("QUICKSTART", "Inserted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); }
OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges();
for (OrderedCollectionChangeSet.Range range : modifications) {
Log.v("QUICKSTART", "Updated range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); }
}
});
// all tasks in the realm
val tasks : RealmResults<Task> = realm.where<Task>().findAllAsync()
tasks.addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<Task>> { collection, changeSet ->
// process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate
val deletions = changeSet.deletionRanges
for (i in deletions.indices.reversed()) {
val range = deletions[i]
Log.v("QUICKSTART", "Deleted range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
val insertions = changeSet.insertionRanges
for (range in insertions) {
Log.v("QUICKSTART", "Inserted range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
val modifications = changeSet.changeRanges
for (range in modifications) {
Log.v("QUICKSTART", "Updated range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
})

Se você estiver executando este projeto em um novo projeto do Android Studio, poderá copiar e colar este arquivo no MainActivity do seu aplicativo -- apenas lembre-se de:

  • use uma declaração de pacote no topo do arquivo para seu próprio projeto

  • atualize as declarações import para Task e TaskStatus se você estiver usando Java

Task.java
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.Required;
public class Task extends RealmObject {
@PrimaryKey private String name;
@Required private String status = TaskStatus.Open.name();
public void setStatus(TaskStatus status) { this.status = status.name(); }
public String getStatus() { return this.status; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Task(String _name) { this.name = _name; }
public Task() {}
}
TaskStatus.java
public enum TaskStatus {
Open("Open"),
InProgress("In Progress"),
Complete("Complete");
String displayName;
TaskStatus(String displayName) {
this.displayName = displayName;
}
}
MainActivity.java
import io.realm.OrderedCollectionChangeSet;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import io.realm.OrderedRealmCollectionChangeListener;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmResults;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import com.mongodb.realm.examples.model.java.Task;
import com.mongodb.realm.examples.model.java.TaskStatus;
public class MainActivity extends AppCompatActivity {
Realm uiThreadRealm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Realm.init(this); // context, usually an Activity or Application
String realmName = "My Project";
RealmConfiguration config = new RealmConfiguration.Builder().name(realmName).build();
uiThreadRealm = Realm.getInstance(config);
addChangeListenerToRealm(uiThreadRealm);
FutureTask<String> Task = new FutureTask(new BackgroundQuickStart(), "test");
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(Task);
}
private void addChangeListenerToRealm(Realm realm) {
// all Tasks in the realm
RealmResults<Task> Tasks = uiThreadRealm.where(Task.class).findAllAsync();
Tasks.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Task>>() {
@Override
public void onChange(RealmResults<Task> collection, OrderedCollectionChangeSet changeSet) {
// process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate
OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges();
for (OrderedCollectionChangeSet.Range range : deletions) {
Log.v("QUICKSTART", "Deleted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1));
}
OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges();
for (OrderedCollectionChangeSet.Range range : insertions) {
Log.v("QUICKSTART", "Inserted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); }
OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges();
for (OrderedCollectionChangeSet.Range range : modifications) {
Log.v("QUICKSTART", "Updated range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); }
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// the ui thread realm uses asynchronous transactions, so we can only safely close the realm
// when the activity ends and we can safely assume that those transactions have completed
uiThreadRealm.close();
}
public class BackgroundQuickStart implements Runnable {
@Override
public void run() {
String realmName = "My Project";
RealmConfiguration config = new RealmConfiguration.Builder().name(realmName).build();
Realm backgroundThreadRealm = Realm.getInstance(config);
Task Task = new Task("New Task");
backgroundThreadRealm.executeTransaction (transactionRealm -> {
transactionRealm.insert(Task);
});
// all Tasks in the realm
RealmResults<Task> Tasks = backgroundThreadRealm.where(Task.class).findAll();
// you can also filter a collection
RealmResults<Task> TasksThatBeginWithN = Tasks.where().beginsWith("name", "N").findAll();
RealmResults<Task> openTasks = Tasks.where().equalTo("status", TaskStatus.Open.name()).findAll();
Task otherTask = Tasks.get(0);
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction( transactionRealm -> {
Task innerOtherTask = transactionRealm.where(Task.class).equalTo("_id", otherTask.getName()).findFirst();
innerOtherTask.setStatus(TaskStatus.Complete);
});
Task yetAnotherTask = Tasks.get(0);
String yetAnotherTaskName = yetAnotherTask.getName();
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction( transactionRealm -> {
Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo("_id", yetAnotherTaskName).findFirst();
innerYetAnotherTask.deleteFromRealm();
});
// because this background thread uses synchronous realm transactions, at this point all
// transactions have completed and we can safely close the realm
backgroundThreadRealm.close();
}
}
}
MainActivity.kt
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.util.Log
import io.realm.*
import io.realm.annotations.PrimaryKey
import io.realm.annotations.Required
import io.realm.kotlin.where
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.FutureTask
class MainActivity : AppCompatActivity() {
lateinit var uiThreadRealm: Realm
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Realm.init(this) // context, usually an Activity or Application
val realmName: String = "My Project"
val config = RealmConfiguration.Builder()
.name(realmName)
.build()
uiThreadRealm = Realm.getInstance(config)
addChangeListenerToRealm(uiThreadRealm)
val task : FutureTask<String> = FutureTask(BackgroundQuickStart(), "test")
val executorService: ExecutorService = Executors.newFixedThreadPool(2)
executorService.execute(task)
}
fun addChangeListenerToRealm(realm : Realm) {
// all tasks in the realm
val tasks : RealmResults<Task> = realm.where<Task>().findAllAsync()
tasks.addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<Task>> { collection, changeSet ->
// process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate
val deletions = changeSet.deletionRanges
for (i in deletions.indices.reversed()) {
val range = deletions[i]
Log.v("QUICKSTART", "Deleted range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
val insertions = changeSet.insertionRanges
for (range in insertions) {
Log.v("QUICKSTART", "Inserted range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
val modifications = changeSet.changeRanges
for (range in modifications) {
Log.v("QUICKSTART", "Updated range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
})
}
override fun onDestroy() {
super.onDestroy()
// the ui thread realm uses asynchronous transactions, so we can only safely close the realm
// when the activity ends and we can safely assume that those transactions have completed
uiThreadRealm.close()
}
class BackgroundQuickStart : Runnable {
override fun run() {
val realmName: String = "My Project"
val config = RealmConfiguration.Builder().name(realmName).build()
val backgroundThreadRealm : Realm = Realm.getInstance(config)
val task : Task = Task()
task.name = "New Task"
backgroundThreadRealm.executeTransaction { transactionRealm ->
transactionRealm.insert(task)
}
// all tasks in the realm
val tasks : RealmResults<Task> = backgroundThreadRealm.where<Task>().findAll()
// you can also filter a collection
val tasksThatBeginWithN : List<Task> = tasks.where().beginsWith("name", "N").findAll()
val openTasks : List<Task> = tasks.where().equalTo("status", TaskStatus.Open.name).findAll()
val otherTask: Task = tasks[0]!!
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction { transactionRealm ->
val innerOtherTask : Task = transactionRealm.where<Task>().equalTo("name", otherTask.name).findFirst()!!
innerOtherTask.status = TaskStatus.Complete.name
}
val yetAnotherTask: Task = tasks.get(0)!!
val yetAnotherTaskName: String = yetAnotherTask.name
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction { transactionRealm ->
val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo("name", yetAnotherTaskName).findFirst()!!
innerYetAnotherTask.deleteFromRealm()
}
// because this background thread uses synchronous realm transactions, at this point all
// transactions have completed and we can safely close the realm
backgroundThreadRealm.close()
}
}
}
enum class TaskStatus(val displayName: String) {
Open("Open"),
InProgress("In Progress"),
Complete("Complete"),
}
open class Task() : RealmObject() {
@PrimaryKey
var name: String = "task"
@Required
var status: String = TaskStatus.Open.name
var statusEnum: TaskStatus
get() {
// because status is actually a String and another client could assign an invalid value,
// default the status to "Open" if the status is unreadable
return try {
TaskStatus.valueOf(status)
} catch (e: IllegalArgumentException) {
TaskStatus.Open
}
}
set(value) { status = value.name }
}

A execução do código acima deve produzir um resultado semelhante ao seguinte:

Successfully authenticated anonymously.
Updated range: 0 to 1
Deleted range: 0 to 1
Successfully logged out.

Próximo

Bem-vindo aos Docs do Atlas Device SDK