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

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 3

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

Vinícius Thiengo
(2050)
Go-ahead
"O método consciente de tentativa e erro é mais bem-sucedido que o planejamento de um gênio isolado."
Peter Skillman
Prototipagem Android
Capa do curso Prototipagem Profissional de Aplicativos
TítuloAndroid: Prototipagem Profissional de Aplicativos
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
Acessar Curso
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Lendo
TítuloManual de DevOps: como obter agilidade, confiabilidade e segurança em organizações tecnológicas
CategoriaEngenharia de Software
Autor(es)Gene Kim, Jez Humble, John Willis, Patrick Debois
EditoraAlta Books
Edição1ª
Ano2018
Páginas464
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?

Na parte 3 da série Persistência Local de Dados com Realm Library no Android, é apresentada a implementação dos métodos que vão permitir a inserção dinâmica do bloco de Views responsável por permitir a entrada de cada nota para cada disciplina cursada pelo estudante. A Activity que receberá as modificações é a AddUpdateStudentActivity junto ao novo adapter DisciplineSpinnerAdapter.

O primeiro passo é adicionar o layout box_discipline_grade.xml que terá o conjunto Spinner (onde vem as disciplinas já cadastradas no APP), EditText (a nota do aluno na disciplina) e Button (permitirá a inclusão de um listesner para a remoção do box de nota), segue código:

<?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>

 

O passo 2 é atualizar o layout activity_add_update_student.xml que terá a parte de notas e o button que permitirá o user / professor adicionar outras disciplinas e notas ao aluno, segue código:

<?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" />

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bt_add_update"
android:layout_below="@+id/et_name"
android:fillViewport="true">

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

<include layout="@layout/box_discipline_grade" />

<Button
android:id="@+id/bt_add"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="5dp"
android:background="#dddddd"
android:gravity="center"
android:onClick="callAddGrade"
android:text="Add"
android:textColor="#000" />

</LinearLayout>
</ScrollView>

<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>

 

Note que temos um ScrollView para manter a possibilidade do user adicionar quantas disciplinas forem necessárias (tendo em mente que haverá muitas disciplinas e não disciplinas repetidas para cada aluno) sem colocar o conteúdo abaixo do button "ADD" da Activity AddUpdateStudentsActivity.

Logo como sendo o primeiro e único filho do ScrollView, temos o View LinearLayout que será o container chave para que possamos adicionar mais box_discipline_grade.xml de forma dinâmica na tela. O LinearLayout e o button bt_add são os elementos chave, sempre um novo bloco de nota entra acima desse button.

Segue código do método createGradeForView() de AddUpdateStudentActivity, que junto ao método getDisciplinePosition() adiciona a Activity um novo bloco de notas vazio ou um já preenchido quando em modo update:

private void createGradeForView( View view, RealmResults<Discipline> disciplines, Grade grade ){
LayoutInflater inflater = this.getLayoutInflater();
LinearLayout llChild = (LinearLayout) inflater.inflate(R.layout.box_discipline_grade, null);

Spinner spDiscipline = (Spinner) llChild.findViewById(R.id.sp_discipline);
spDiscipline.setAdapter( new DisciplineSpinnerAdapter( this, disciplines ));
if( grade != null ){
spDiscipline.setSelection(getDisciplinePosition(disciplines, grade.getDiscipline()));
}

EditText etGrade = (EditText) llChild.findViewById(R.id.et_grade);
if( grade != null ){
etGrade.setText(String.valueOf(grade.getGrade()));
}

View btRemove = llChild.findViewById(R.id.bt_remove);
btRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callRemoveGrade( v );
}
});

float scale = getResources().getDisplayMetrics().density;
int margin = (int)( 5 * scale + 0.5f );

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins( margin, margin, margin, margin );
llChild.setLayoutParams( layoutParams );

LinearLayout llParent = (LinearLayout) view.getParent();
llParent.addView( llChild, llParent.getChildCount() - 1 );
}

 

Note que devido a perda de propriedades no momento de inflar o layout de llChild, propriedades como width, height e margin temos de setar os valores reais para esses atributos novamente via LayoutParams no code.

Segue código do método getDisciplinePosition():

private int getDisciplinePosition( RealmResults<Discipline> disciplines, Discipline discipline ){
for( int i = 0; i < disciplines.size(); i++ ){
if( disciplines.get(i).getId() == discipline.getId() ){
return( i );
}
}
return(0);
}

 

O método acima vai permitir acessar a posição correta da disciplina no Spinner do bloco, em modo update.

Precisamos então da variavel de instancia disciplines, do adapter DisciplineSpinnerAdapter, do método listener callRemoveGrade() que será vinculado ao listener de click do button bt_remove e do outro método listener (que já está vinculado via xml onClick ao button bt_add) callAddGrade().

Primeiro disciplines nas declarações de varaiveis de instancia da Activity:

...
private Realm realm;
private RealmResults<Student> students;
private RealmResults<Discipline> disciplines;

private Student student;
private EditText etName;
...

 

Logo depois a inicialização de disciplines dentro do onCreate():

...
disciplines = realm.where(Discipline.class).findAll();

Spinner spDiscipline = (Spinner) findViewById(R.id.sp_discipline);
spDiscipline.setAdapter( new DisciplineSpinnerAdapter( this, disciplines ));

View btRemove = findViewById(R.id.bt_remove);
btRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callRemoveGrade( v );
}
});
...

 

Nessa parte já é colocado também o trecho de código responsável por já colocar um comportamento de click listener no button bt_remove e prencher o Spinner sp_discipline. Ambos são do primeiro bloco de nota (grade) que já vem no layout sem a necessidade de uso do método createGradeForView() para criá-lo.

Segue código do método listener callRemoveGrade():

private void callRemoveGrade( View view ){
LinearLayout llParent = (LinearLayout) view.getParent().getParent();

if( llParent.getChildCount() > 2 ){
llParent.removeView((LinearLayout) view.getParent());
}
}

 

O que ele recebe como parêmtro é o button de remoção do bloco de nota que teve seu respectivo button de remover clicado, então a chamada view.getParent().getParent() nos permiti acessar o LinearLayout que o primeiro filho do ScrollView (comentado anteriormente) e container dos blocos de notas (LinearLayout) e do button que adiciona mais blocos. Note que a verificação se o número de elementos filhos é maior que 2 nos permite sempre ter na tela de cadastro / update de estudante as views button para adicionar mais blocos de notas e ao menos um bloco de nota que é um LinearLayout e seus views filho. O cast é necessário para a remossão e utilização de métodos especificos não suportados por ViewGroup (retornado por getParent()).

Agora seguimos com o código do método callAddGrade():

public void callAddGrade( View view ){
LinearLayout llParent = (LinearLayout) view.getParent();

if( llParent.getChildCount() - 1 == disciplines.size() ){
Toast.makeText(this, "Máximo de disciplinas atingido", Toast.LENGTH_SHORT).show();
return;
}

createGradeForView( view, disciplines, null );
}

Note que nele verificamos se o total de blocos de notas dentro do LinearLayout container é igual ao tamanho máximo de disciplines, colocamos isso como sendo uma regra de negócio do sistema, não permitir disciplinas repetidas para o mesmo estudante. O - 1 é necessário para não ser contado o button bt_add.

Enfim o código do DisciplineSpinnerAdapter para que seja possível colocar as disciplinas nos spinners de cada bloco de notas, segue código:

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

import br.com.thiengo.realmstudents.R;
import br.com.thiengo.realmstudents.domain.Discipline;
import io.realm.RealmBaseAdapter;
import io.realm.RealmResults;

public class DisciplineSpinnerAdapter extends RealmBaseAdapter<Discipline> implements ListAdapter {

public DisciplineSpinnerAdapter(Context context, RealmResults<Discipline> realmResults){
super(context, realmResults, false);
}

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

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

holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
}
else{
holder = (CustomViewHolder) convertView.getTag();
}

final Discipline d = realmResults.get(position);
holder.tvName.setText(d.getName());

return convertView;
}

private static class CustomViewHolder{
TextView tvName;
}
}

 

Note que o DisciplineAdapter sem os buttons e com o layout item_discipline_spinner.xml que é o layout item_discipline.xml também sem os buttons:

<?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="3dp">

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

 

Com isso terminamos a parte 3 dessa série no Android. O código completo do projeto pode ser acessado no GitHub: https://github.com/viniciusthiengo/realm-students

Na parte 4 vamos colocar esse form de inserção de estudante para funcionar.

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

Segue vídeo de implementação dessa parte 3:

 

Vlw.

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 2Persistência de Dados Com Realm no Android - Parte 2Android
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

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...