persistência com realm.io
TRANSCRIPT
Persistência com Realm.io
Pedro Salomão @ppgsalomao
#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 knowAndroid Threads
ProGuard
Realm.io
Documentaçãohttps://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
Modelopublic 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 - ModelosTodos 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 - ModelosTodos 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 - ModelosNome 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çõesRealm 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 objetosUser user = realm.createObject(User.class); // Create a new objectuser.setName("John");user.setEmail("[email protected]");
User user = new User("John");user.setEmail("[email protected]");
User realmUser = realm.copyToRealm(user);
String json = ...;realm.createObjectFromJson(User.class, json);
String json = ...;realm.createOrUpdateObjectFromJson(User.class, json);
Tips & Tricks - ObjetosManipulaçã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çõesquery.equalTo("nome", "Joao");query.or().equalTo("nome", "Pedro");
// Executa a consultaRealmResults<User> resultado = query.findAll();
// Fazendo tudo juntoRealmResults<User> resultado = realm.where(User.class) .equalTo("nome", "Joao") .or() .equalTo("nome", "Pedro") .findAll();
Consultas// Agrupando Operadores LógicosRealmResults<User> resultado = realm.where(User.class) .greaterThan(“idade”, 10) .beginGroup() .equalTo("nome", "Joao") .or() .contains("nome", “Paulo") .endGroup() .findAll();
// Encadeando consultasRealmResults<User> adolescentes = realm.where(User.class) .between(“idade”, 13, 20) .findAll();
User primeiroJoao = adolescentes.where() .equalTo("nome", "Joao") .findFirst();
Consultas// Funções de agregaçãolong 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 resultadoRealmResults<User> result = realm.where(User.class).findAll();result.sort("idade"); // Sort ascendingresult.sort(""idade", RealmResults.SORT_ORDER_DESCENDING);
// Ordenando já na consultaRealmResults<User> result = realm.where(User.class).findAllSorted("idade");
Consultaspublic 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 - ConsultasCuidado 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 - Geralpublic 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 - GeralCuidado 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