Persistência com Realm.io
Pedro Salomão
@ppgsalomao
ppgsalomao@gmail.com / pedro@onyo.com
#whoami
Persistência
O que é persistência?
Quando devemos buscar
uma biblioteca?
Realm resolve todos os
problemas de persistência?
Existe bala de prata?
O que precisamos saber
para usar o Realm?
Must know
Android Threads
ProGuard
Realm.io
Documentação
https://realm.io/
buildscript	
  {	
  
	
  	
  	
  	
  repositories	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  jcenter()	
  
	
  	
  	
  	
  }	
  
}	
  
dependencies	
  {	
  
	
  	
  	
  	
  compile	
  'io.realm:realm-­‐android:0.82.2'	
  
}
../your_module/build.gradle
-­‐keep	
  class	
  io.realm.annotations.RealmModule	
  
-­‐keep	
  @io.realm.annotations.RealmModule	
  class	
  *	
  
-­‐dontwarn	
  javax.**	
  
-­‐dontwarn	
  io.realm.**
../your_module/proguard-­‐rules.pro
Modelos
Modelo
public class User extends RealmObject {
private String name;
private boolean boolValue;
private short number;
private int number2;
private long number3;
private float fractionNumber;
private double fractionNumber2;
private byte[] bytes;
private Date date;
private RealmObject object;
private RealmList<? extends RealmObject> list;
@PrimaryKey
private int id; // inteiros ou String
@Index
private int index; // Tipos primitivos
@Ignore
private int sessionId;
// Getters & Setters padrão
public String getName() { return name; }
public void setName(String name) { this.name = name; }
…
}
Tips & Tricks - Modelos
Todos os inteiros são mapeados para long, inclusive
os Wrappers.
Não é possível armazenar null para nenhum tipo
diferente de RealmObject ou RealmLists.
Os getters e setters são obrigatórios para todas as
propriedades não anotadas com @Ignore.
Getters e Setters são alterados depois pelo Realm,
então qualquer implementação diferente é descartada.
Tips & Tricks - Modelos
Todos os atributos devem ser privados.
Métodos e atributos estáticos são liberados.
@PrimaryKey não pode ser usada em mais de um
atributo.
@PrimaryKey já define implicitamente o @Index para
o atributo.
Tips & Tricks - Modelos
Nome da classe deve ter no máximo 57 caracteres.
Nome de atributo deve ter no máximo 63 caracteres
Datas são armazenadas com precisão de segundos,
no período 13/12/1900 e 19/01/2038.
Strings e byte[] devem ter no máximo 16mb.
Transações
Transações
Realm realm = Realm.getInstance(this);
realm.beginTransaction();
// Insere, altera ou remove objetos da base
realm.commitTransaction();
realm.cancelTransaction();
Realm realm = Realm.getInstance(this);
realm.executeTransaction((realm) -> {
// Insere, altera ou remove objetos da base
});
Realm realm = Realm.getInstance(this);
realm.executeTransaction(new Realm.Transaction() {

@Override

public void execute(Realm realm) {
// Insere, altera ou remove objetos da base
}
});
Explicitamente
Realm + Lambda
Realm
Tips & Tricks - Transações
São obrigatórias para qualquer alteração na base de
dados.
Dados só são persistidos no disco após o commit da
transação.
Operações de escrita no banco bloqueiam outras
transações de escrita e podem demorar.
ATENÇÃO: Não faça operações de escrita no banco
na UI Thread.
Tips & Tricks - Transações
Divida o processo em criar objetos e gravar no
banco.
Escritas no banco não bloqueiam a leitura do
mesmo.
Transações aninhadas (uma transação dentro de outra
transação) não são suportadas e geram exceção.
Gravando no Banco
Criando objetos
User user = realm.createObject(User.class); // Create a new object
user.setName("John");
user.setEmail("john@corporation.com");
User user = new User("John");
user.setEmail("john@corporation.com");
User realmUser = realm.copyToRealm(user);
String json = ...;
realm.createObjectFromJson(User.class, json);
String json = ...;
realm.createOrUpdateObjectFromJson(User.class, json);
Tips & Tricks - Objetos
Manipulação de objetos deve sempre ocorrer dentro
de uma transação.
O objeto só pode ser usado na Thread em que ele foi
criado.
Pode-se criar um Wrapper para o objeto para poder
transitá-lo entre threads e inserir métodos nele.
Cuidado com restrições definidas por PrimaryKey ao
inserir ou atualizar objetos.
Fazendo consultas
Consultas
// Criando a consulta para pegar todos os usuários.
RealmQuery<User> query = realm.where(User.class);
// Adiciona as condições
query.equalTo("nome", "Joao");
query.or().equalTo("nome", "Pedro");
// Executa a consulta
RealmResults<User> resultado = query.findAll();
// Fazendo tudo junto
RealmResults<User> resultado = realm.where(User.class)
.equalTo("nome", "Joao")
.or()
.equalTo("nome", "Pedro")
.findAll();
Consultas
// Agrupando Operadores Lógicos
RealmResults<User> resultado = realm.where(User.class)
.greaterThan(“idade”, 10)
.beginGroup()
.equalTo("nome", "Joao")
.or()
.contains("nome", “Paulo")
.endGroup()
.findAll();
// Encadeando consultas
RealmResults<User> adolescentes = realm.where(User.class)
.between(“idade”, 13, 20)
.findAll();
User primeiroJoao = adolescentes.where()
.equalTo("nome", "Joao")
.findFirst();
Consultas
// Funções de agregação
long sum = resultado.sum("idade").longValue();
long min = resultado.min("idade").longValue();
long max = resultado.max("idade").longValue();
double average = resultado.average("idade");
long matches = result.size();
// Ordenando o resultado
RealmResults<User> result = realm.where(User.class).findAll();
result.sort("idade"); // Sort ascending
result.sort(""idade", RealmResults.SORT_ORDER_DESCENDING);
// Ordenando já na consulta
RealmResults<User> result = realm.where(User.class).findAllSorted("idade");
Consultas
public class User extends RealmObject {
...
private RealmList<Email> emails;
...
}
public class Email extends RealmObject {
...
private boolean active;
...
}
RealmResults<Contact> contacts = realm.where(Contact.class)
.equalTo("emails.active", true)
.findAll();
public class User extends RealmObject {
...
private RealmList<Email> emails;
...
}
public class Email extends RealmObject {
...
private boolean active;
...
}
RealmResults<Contact> contacts = realm.where(Contact.class)
.equalTo("emails.active", true)
.equalTo("emails.active", false)
.findAll();
Tips & Tricks - Consultas
Cuidado com o nome das propriedades na hora de
filtrar para evitar erros de digitação.
Só é possível ordenar utilizando os campos que
estão no modelo de retorno.
Não é possível fazer GROUP BY como é feito no
SQL.
Todas as consultas são LAZY.
Removendo da Base
Remoção
// Remover o objeto de um resultado.
result.remove(0);
result.removeLast();
// Remover um objeto específico.
User usuario = result.get(5);
usuario.removeFromRealm();
// Remover todos os objetos de um resultado.
result.clear();
Utilitários
Integrando com a Aplicação
Utilitários
Notificações
Migrações
Criptografia
RealmBaseAdapter
Integração
com outras
bibliotecas
Parceler
Robolectric
Geral
Tips & Tricks - Geral
public abstract class AbstractRealmPersistenceService {
private Context context;
private Realm realm;
private int currentThreadId;
public AbstractRealmPersistenceService(Context context) {
this(context, null);
}
public AbstractRealmPersistenceService(Context context, Realm realm) {
this.context = context;
this.realm = realm;
this.currentThreadId = android.os.Process.myTid();
}
protected Realm getRealm() {
this.reloadRealm();
return this.realm;
}
private void reloadRealm() {
int threadId = android.os.Process.myTid();
if(this.currentThreadId != threadId || this.realm == null) {
this.realm = Realm.getInstance(this.context);
this.currentThreadId = threadId;
}
}
}
Tips & Tricks - Geral
Cuidado com a transição entre Threads, principalmente
se você faz operações em Background.
Dúvidas?
Pedro Salomão
@ppgsalomao
Obrigado!
Estamos contratando!
Pedro Salomão
@ppgsalomao
ppgsalomao@gmail.com / pedro@onyo.com

Persistência com Realm.io

  • 1.
    Persistência com Realm.io PedroSalomão @ppgsalomao ppgsalomao@gmail.com / pedro@onyo.com
  • 2.
  • 3.
    Persistência O que épersistência? Quando devemos buscar uma biblioteca? Realm resolve todos os problemas de persistência? Existe bala de prata?
  • 4.
    O que precisamossaber para usar o Realm?
  • 5.
  • 6.
  • 7.
  • 8.
    buildscript  {          repositories  {                  jcenter()          }   }   dependencies  {          compile  'io.realm:realm-­‐android:0.82.2'   } ../your_module/build.gradle -­‐keep  class  io.realm.annotations.RealmModule   -­‐keep  @io.realm.annotations.RealmModule  class  *   -­‐dontwarn  javax.**   -­‐dontwarn  io.realm.** ../your_module/proguard-­‐rules.pro
  • 9.
  • 10.
    Modelo public class Userextends RealmObject { private String name; private boolean boolValue; private short number; private int number2; private long number3; private float fractionNumber; private double fractionNumber2; private byte[] bytes; private Date date; private RealmObject object; private RealmList<? extends RealmObject> list; @PrimaryKey private int id; // inteiros ou String @Index private int index; // Tipos primitivos @Ignore private int sessionId; // Getters & Setters padrão public String getName() { return name; } public void setName(String name) { this.name = name; } … }
  • 11.
    Tips & Tricks- Modelos Todos os inteiros são mapeados para long, inclusive os Wrappers. Não é possível armazenar null para nenhum tipo diferente de RealmObject ou RealmLists. Os getters e setters são obrigatórios para todas as propriedades não anotadas com @Ignore. Getters e Setters são alterados depois pelo Realm, então qualquer implementação diferente é descartada.
  • 12.
    Tips & Tricks- Modelos Todos os atributos devem ser privados. Métodos e atributos estáticos são liberados. @PrimaryKey não pode ser usada em mais de um atributo. @PrimaryKey já define implicitamente o @Index para o atributo.
  • 13.
    Tips & Tricks- Modelos Nome da classe deve ter no máximo 57 caracteres. Nome de atributo deve ter no máximo 63 caracteres Datas são armazenadas com precisão de segundos, no período 13/12/1900 e 19/01/2038. Strings e byte[] devem ter no máximo 16mb.
  • 14.
  • 15.
    Transações Realm realm =Realm.getInstance(this); realm.beginTransaction(); // Insere, altera ou remove objetos da base realm.commitTransaction(); realm.cancelTransaction(); Realm realm = Realm.getInstance(this); realm.executeTransaction((realm) -> { // Insere, altera ou remove objetos da base }); Realm realm = Realm.getInstance(this); realm.executeTransaction(new Realm.Transaction() {
 @Override
 public void execute(Realm realm) { // Insere, altera ou remove objetos da base } }); Explicitamente Realm + Lambda Realm
  • 16.
    Tips & Tricks- Transações São obrigatórias para qualquer alteração na base de dados. Dados só são persistidos no disco após o commit da transação. Operações de escrita no banco bloqueiam outras transações de escrita e podem demorar. ATENÇÃO: Não faça operações de escrita no banco na UI Thread.
  • 17.
    Tips & Tricks- Transações Divida o processo em criar objetos e gravar no banco. Escritas no banco não bloqueiam a leitura do mesmo. Transações aninhadas (uma transação dentro de outra transação) não são suportadas e geram exceção.
  • 18.
  • 19.
    Criando objetos User user= realm.createObject(User.class); // Create a new object user.setName("John"); user.setEmail("john@corporation.com"); User user = new User("John"); user.setEmail("john@corporation.com"); User realmUser = realm.copyToRealm(user); String json = ...; realm.createObjectFromJson(User.class, json); String json = ...; realm.createOrUpdateObjectFromJson(User.class, json);
  • 20.
    Tips & Tricks- Objetos Manipulação de objetos deve sempre ocorrer dentro de uma transação. O objeto só pode ser usado na Thread em que ele foi criado. Pode-se criar um Wrapper para o objeto para poder transitá-lo entre threads e inserir métodos nele. Cuidado com restrições definidas por PrimaryKey ao inserir ou atualizar objetos.
  • 21.
  • 22.
    Consultas // Criando aconsulta para pegar todos os usuários. RealmQuery<User> query = realm.where(User.class); // Adiciona as condições query.equalTo("nome", "Joao"); query.or().equalTo("nome", "Pedro"); // Executa a consulta RealmResults<User> resultado = query.findAll(); // Fazendo tudo junto RealmResults<User> resultado = realm.where(User.class) .equalTo("nome", "Joao") .or() .equalTo("nome", "Pedro") .findAll();
  • 23.
    Consultas // Agrupando OperadoresLógicos RealmResults<User> resultado = realm.where(User.class) .greaterThan(“idade”, 10) .beginGroup() .equalTo("nome", "Joao") .or() .contains("nome", “Paulo") .endGroup() .findAll(); // Encadeando consultas RealmResults<User> adolescentes = realm.where(User.class) .between(“idade”, 13, 20) .findAll(); User primeiroJoao = adolescentes.where() .equalTo("nome", "Joao") .findFirst();
  • 24.
    Consultas // Funções deagregação long sum = resultado.sum("idade").longValue(); long min = resultado.min("idade").longValue(); long max = resultado.max("idade").longValue(); double average = resultado.average("idade"); long matches = result.size(); // Ordenando o resultado RealmResults<User> result = realm.where(User.class).findAll(); result.sort("idade"); // Sort ascending result.sort(""idade", RealmResults.SORT_ORDER_DESCENDING); // Ordenando já na consulta RealmResults<User> result = realm.where(User.class).findAllSorted("idade");
  • 25.
    Consultas public class Userextends RealmObject { ... private RealmList<Email> emails; ... } public class Email extends RealmObject { ... private boolean active; ... } RealmResults<Contact> contacts = realm.where(Contact.class) .equalTo("emails.active", true) .findAll(); public class User extends RealmObject { ... private RealmList<Email> emails; ... } public class Email extends RealmObject { ... private boolean active; ... } RealmResults<Contact> contacts = realm.where(Contact.class) .equalTo("emails.active", true) .equalTo("emails.active", false) .findAll();
  • 26.
    Tips & Tricks- Consultas Cuidado com o nome das propriedades na hora de filtrar para evitar erros de digitação. Só é possível ordenar utilizando os campos que estão no modelo de retorno. Não é possível fazer GROUP BY como é feito no SQL. Todas as consultas são LAZY.
  • 27.
  • 28.
    Remoção // Remover oobjeto de um resultado. result.remove(0); result.removeLast(); // Remover um objeto específico. User usuario = result.get(5); usuario.removeFromRealm(); // Remover todos os objetos de um resultado. result.clear();
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
    Tips & Tricks- Geral public abstract class AbstractRealmPersistenceService { private Context context; private Realm realm; private int currentThreadId; public AbstractRealmPersistenceService(Context context) { this(context, null); } public AbstractRealmPersistenceService(Context context, Realm realm) { this.context = context; this.realm = realm; this.currentThreadId = android.os.Process.myTid(); } protected Realm getRealm() { this.reloadRealm(); return this.realm; } private void reloadRealm() { int threadId = android.os.Process.myTid(); if(this.currentThreadId != threadId || this.realm == null) { this.realm = Realm.getInstance(this.context); this.currentThreadId = threadId; } } }
  • 34.
    Tips & Tricks- Geral Cuidado com a transição entre Threads, principalmente se você faz operações em Background.
  • 35.
  • 36.