Persistência de Dados Com Realm no Android - Parte 2

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /Persistência de Dados Com Realm no Android - Parte 2

Persistência de Dados Com Realm no Android - Parte 2

Vinícius Thiengo
(2059) (2)
Go-ahead
"É fácil dar um pequeno passo. A verdadeira pergunta é: você está disposto a dar um número suficiente deles? Quando você esta, tudo está ao seu alcance."
R. Marston
Kotlin Android
Capa do livro Mapas Android de Alta Qualidade - Masterização Android
TítuloMapas Android de Alta Qualidade - Masterização Android
CategoriasAndroid, Kotlin, Masterização, Especialização
AutorVinícius Thiengo
Edição
Ano2020
Capítulos11
Páginas166
Acessar Livro
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

Opa, blz?

Nessa parte 2 da série persistência local no Android com Realm, é apresentado a construção das Activities de Students (Students Activity e AddUpdateStudentActivity) além de algumas atualizações do domínio do problema (Student e Grade) junto a adição de um novo adapter, StudentAdapter, para ser carregado junto ao ListView de Student.

Começamos pelo domínio do problema colocando a classe Student extends RealmObject além da adição do atributo RealmList<Grade> que será responsável por manter as notas do estudante junto ao objeto referente a ele. Note que no caso de lista, apesar de posteriormente ser utilizado um LinkedList para preencher a lista grades de Student, o tipo dela tem de ser RealmList<T>, segue código:

import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;

public class Student extends RealmObject {
public static final String ID = "br.com.thiengo.realmexample.domain.Student.ID";

@PrimaryKey
private long id;
private String name;
private String email;
private RealmList<Grade> grades;

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public RealmList<Grade> getGrades() {
return grades;
}

public void setGrades(RealmList<Grade> grades) {
this.grades = grades;
}
}

 

Logo depois devemos adicionar a classe Grade que será responsável por ter a disciplina junto a nota do aluno na referente disciplina:

import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;

public class Grade extends RealmObject {
@PrimaryKey
private long id;
private Discipline discipline;
private double grade;


public Discipline getDiscipline() {
return discipline;
}

public void setDiscipline(Discipline discipline) {
this.discipline = discipline;
}

public double getGrade() {
return grade;
}

public void setGrade(double grade) {
this.grade = grade;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}
}

 

Com as configurações das classes do domínio do problema atualizadas, vamos a MainActivity colocar o button de acesso a Activity StudentsActivity para funcionar, segue código:

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

import br.com.thiengo.realmstudents.domain.Discipline;
import br.com.thiengo.realmstudents.domain.Student;
import io.realm.Realm;
import io.realm.RealmResults;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

@Override
protected void onResume() {
super.onResume();

Button btDisciplines = (Button) findViewById(R.id.bt_disciplines);
Button btStudents = (Button) findViewById(R.id.bt_students);

Realm realm = Realm.getDefaultInstance();
RealmResults<Discipline> disciplines = realm.where(Discipline.class).findAll();
RealmResults<Student> students = realm.where(Student.class).findAll();

btDisciplines.setText( "Disciplinas ("+disciplines.size()+")" );
btStudents.setText( "Estudantes ("+students.size()+")" );
realm.close();
}


public void callDisciplines( View view){
Intent it = new Intent(this, DisciplinesActivity.class);
startActivity(it);
}


public void callStudents( View view){
Intent it = new Intent(this, StudentsActivity.class);
startActivity(it);
}
}

 

Ai sim vamos ao código de StudentsActivity, que é bem similar ao código de DisciplinesActivity do vídeo 1 da série, mudando apenas Discipline por Student (como apresentado no vídeo via Ctrl + A e Ctrl + R no AndroidStudio):

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ListView;

import br.com.thiengo.realmstudents.adapter.StudentAdapter;
import br.com.thiengo.realmstudents.domain.Student;
import io.realm.Realm;
import io.realm.RealmChangeListener;
import io.realm.RealmResults;

public class StudentsActivity extends AppCompatActivity {

private Realm realm;
private RealmResults<Student> students;
private RealmChangeListener realmChangeListener;
private ListView lvStudents;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_students);

realm = Realm.getDefaultInstance();

realmChangeListener = new RealmChangeListener() {
@Override
public void onChange() {
((StudentAdapter) lvStudents.getAdapter()).notifyDataSetChanged();
}
};

realm.addChangeListener(realmChangeListener);
students = realm.where( Student.class ).findAll();

lvStudents = (ListView) findViewById(R.id.lv_students);
lvStudents.setAdapter( new StudentAdapter( this, students, false ));
}


@Override
protected void onDestroy() {
realm.removeAllChangeListeners();
realm.close();
super.onDestroy();

}


public void callAddStudent( View view){
Intent it = new Intent( this, AddUpdateStudentActivity.class );
startActivity(it);
}
}

 

Sege layout xml de StudentsActivity (activity_students.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ListView
android:id="@+id/lv_students"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:onClick="callAddStudent"
android:text="Add estudante" />

</LinearLayout>

 

Segue adapter StudentAdapter, para se possível carregar os dados de Student no ListView lv_students:

import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.TextView;

import br.com.thiengo.realmstudents.AddUpdateStudentActivity;
import br.com.thiengo.realmstudents.R;
import br.com.thiengo.realmstudents.domain.Student;
import io.realm.Realm;
import io.realm.RealmBaseAdapter;
import io.realm.RealmResults;

public class StudentAdapter extends RealmBaseAdapter<Student> implements ListAdapter {

private Realm realm;

public StudentAdapter(Context context, RealmResults<Student> realmResults, boolean automaticUpdate){
super(context, realmResults, automaticUpdate);
this.realm = realm;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
CustomViewHolder holder;

if( convertView == null ){
convertView = inflater.inflate(R.layout.item_student, parent, false);
holder = new CustomViewHolder();
convertView.setTag( holder );

holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
holder.btUpdate = (Button) convertView.findViewById(R.id.bt_update);
holder.btRemove = (Button) convertView.findViewById(R.id.bt_remove);
}
else{
holder = (CustomViewHolder) convertView.getTag();
}

final Student s = realmResults.get(position);
holder.tvName.setText( s.getName() );

holder.btUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent it = new Intent(context, AddUpdateStudentActivity.class);
it.putExtra(Student.ID, s.getId());
context.startActivity(it);
}
});

holder.btRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
s.removeFromRealm();
realm.commitTransaction();
realm.close();
}
});

return convertView;
}

private static class CustomViewHolder{
TextView tvName;
Button btUpdate;
Button btRemove;
}
}

 

Exatamente o mesmo que DisciplineAdapter, exceto que estamos com Student ao invés de Discipline. Segue código do layout dos itens plotads pelo adapter, item_student.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="5dp">

<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:textSize="18sp" />

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<Button
android:id="@+id/bt_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Atualizar"
android:textSize="12sp" />

<Button
android:id="@+id/bt_remove"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Remover"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>

 

Seguindo a construção das Actities da entidade Student, vamos a Activity AddUpdateActivityStudent e seu respectivo layout, activity_add_update_student.xml:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import br.com.thiengo.realmstudents.domain.Student;
import io.realm.Realm;
import io.realm.RealmResults;

public class AddUpdateStudentActivity extends AppCompatActivity {

private Realm realm;
private RealmResults<Student> students;

private Student student;
private EditText etName;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_update_student);

student = new Student();
etName = (EditText) findViewById(R.id.et_name);
TextView tvTitle = (TextView) findViewById(R.id.tv_title);
Button btAddUpdate = (Button) findViewById(R.id.bt_add_update);


realm = Realm.getDefaultInstance();
students = realm.where( Student.class ).findAll();

if( getIntent() != null && getIntent().getLongExtra( Student.ID, 0 ) > 0 ){
student.setId( getIntent().getLongExtra( Student.ID, 0 ) );

student = students.where().equalTo("id", student.getId()).findAll().get(0);
etName.setText( student.getName() );
tvTitle.setText("Atualizar disciplina");
btAddUpdate.setText( "Update" );
}
}


@Override
protected void onDestroy() {
realm.close();
super.onDestroy();
}


public void callAddUpdateStudent( View view ){
String label = "atualizado";
if( student.getId() == 0 ){
students.sort( "id", RealmResults.SORT_ORDER_DESCENDING );
long id = students.size() == 0 ? 1 : students.get(0).getId() + 1;
student.setId( id );
label = "adicionado";
}

try{
realm.beginTransaction();
student.setName(etName.getText().toString());
realm.copyToRealmOrUpdate(student);
realm.commitTransaction();

Toast.makeText(AddUpdateStudentActivity.this, "Estudante " + label, Toast.LENGTH_SHORT).show();
finish();
}
catch(Exception e){
e.printStackTrace();
Toast.makeText(AddUpdateStudentActivity.this, "Falhou!", Toast.LENGTH_SHORT).show();
}
}
}

 

Então o layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:gravity="center"
android:padding="5dp"
android:text="Novo estudante"
android:textSize="18sp" />

<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:layout_marginTop="10dp"
android:hint="Nome" />

<Button
android:id="@+id/bt_add_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="5dp"
android:onClick="callAddUpdateStudent"
android:text="Add" />

</RelativeLayout>

 

Com isso, nessa parte 2 do série ficamos por aqui, nas outras partes vamos começar a colocar as funcionalidades de adição dinêmica de bloco de notas (uma série de Views que serão adicionadas dinâmicamente ao perfil do estudante como blocos de notas para as disciplinas).

O código completo pode ser encontrado no GitHub do projeto (https://github.com/viniciusthiengo/realm-students).

Para acessar o site da library Realm: Documentação Realm Library Android

Segue vídeo de implementação da parte 2:

 

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

Persistência de Dados Com Realm no Android - Parte 1Persistência de Dados Com Realm no Android - Parte 1Android
Persistência de Dados Com Realm no Android - Parte 3Persistência de Dados Com Realm no Android - Parte 3Android
Persistência de Dados Com Realm no Android - Parte 4Persistência de Dados Com Realm no Android - Parte 4Android
Persistência de Dados Com Realm no Android - Parte 5Persistência de Dados Com Realm no Android - Parte 5Android

Compartilhar

Comentários Facebook

Comentários Blog (2)

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...
23/09/2016
Olá! Na parte 1 diz que vai ser abordado mais detalhes sobre migrations, porém, nessa parte 2 não possui esta abordagem. Estou com a seguinte situação, estou com uma propriedade de uma classe que herda de RealmObject que está com a notação Ignore, mas eu agora não desejo que ela seja ignorada. Teria como ajustar isso com o migration?

Abraços
Responder
Vinícius Thiengo (0) (0)
24/09/2016
Lucas, blz?
Dê uma olhada nos vídeos até o 5º da série (http://www.thiengo.com.br/migracao-de-dados-realm-library-no-android-parte-6 ) - ou vá direto a ele. Lá tem o migration. Mas fique ciente que não há impedimento em remover o Ignore, alias isso é comum, pois seu código está evoluindo. Pode ser que nem mesmo o migration do Realm sejá necessário. Abraço
Responder