Início rápido - Java SDK
Nesta página
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:
Inicializar Realm
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.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mongodb.example"> <application android:name=".MyApplicationSubclass" ... /> </manifest>
Definir seu modelo de objeto
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 :
import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; import io.realm.annotations.Required; public class Task extends RealmObject { private String name; 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() {} }
public enum TaskStatus { Open("Open"), InProgress("In Progress"), Complete("Complete"); String displayName; TaskStatus(String displayName) { this.displayName = displayName; } }
enum class TaskStatus(val displayName: String) { Open("Open"), InProgress("In Progress"), Complete("Complete"), } open class Task() : RealmObject() { var name: String = "task" 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 } }
Abrir um Realm
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)
Criar, ler, atualizar e excluir objetos
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() { 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() }
Fique atento às mudanças
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>>() { 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}") } })
Exemplo completo
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
paraTask
eTaskStatus
se você estiver usando Java
import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; import io.realm.annotations.Required; public class Task extends RealmObject { private String name; 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() {} }
public enum TaskStatus { Open("Open"), InProgress("In Progress"), Complete("Complete"); String displayName; TaskStatus(String displayName) { this.displayName = displayName; } }
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; 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>>() { 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)); } } }); } 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 { 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(); } } }
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() { var name: String = "task" 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 } }
Saída
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.