Vamos a practicar un poco más con SQLite y Android con otro ejercicio práctico: la creación de una agenda.
Se pretende realizar una aplicación de una agenda en donde se escriba un identificador, el número de teléfono y el nombre de una persona.
Viéndolo desde el punto de vista de diseño de bases de datos o experiencia de usuario el ejercicio no estará muy bien; pero servirá mucho para practicar porque veremos cómo:
Si quieres ver un ejemplo en donde también se Edita y Elimina mira el CRUD de SQLite con Android en donde trabajamos con mascotas. También te invito a que pruebes la app para el control de gastos que publiqué hace algunos días.
A través del post mostraré el código más importante, pero si quieres ver el código completo mira el repositorio en GitHub.
Anteriormente publiqué otros ejercicios con Android:
Otras cosas que he escrito sobre Android las puedes encontrar aquí. Ahora sí, comencemos.
La actividad principal tiene 3 botones: uno para insertar un registro, otro para consultar por identificador y finalmente uno para listar todos los registros existentes.
El código del layout es el siguiente:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btnRegistrar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/registrar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnConsultar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/consultar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnRegistrar" />
<Button
android:id="@+id/btnListar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@string/listar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnConsultar" />
</android.support.constraint.ConstraintLayout>
Para el funcionamiento simplemente instanciamos los botones, agregamos listeners y en cada uno de ellos llamamos a startActivity
pasándole un Intent
que lleva a otra actividad.
package me.parzibyte.agenda;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnRegistrar = findViewById(R.id.btnRegistrar),
btnConsultar = findViewById(R.id.btnConsultar),
btnListar = findViewById(R.id.btnListar);
btnRegistrar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ActivityRegistrar.class);
startActivity(intent);
}
});
btnConsultar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ActivityConsultar.class);
startActivity(intent);
}
});
btnListar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ActivityListar.class);
startActivity(intent);
}
});
}
}
Por el momento, las clases de destino no existen; vamos a crearlas más tarde. Fíjate en que cada llamada a findViewById
tiene que ver con el id que tiene cada botón.
Antes de continuar veremos un archivo de “utilerías” al que yo más bien llamaría Constantes (las típicas constantes estáticas públicas de Java) en donde tenemos la definición de la tabla, los nombres de los campos y esas cosas.
package me.parzibyte.agenda;
public class Utilerias {
public static final String TABLA_PERSONA = "Persona";
public static final String NOMBRE_BD = "agenda";
public static final String CAMPO_ID = "id";
public static final String CAMPO_NOMBRE = "nombre";
public static final String CAMPO_TELEFONO = "telefono";
public static final String CREAR_TABLA_PERSONA = "create table "
+ TABLA_PERSONA
+ " (" + CAMPO_ID + " INTEGER, "
+ CAMPO_NOMBRE + " TEXT, " + CAMPO_TELEFONO + " TEXT)";
}
En el archivo tenemos la creación de tablas y los nombres de los campos de cada tabla.
Para hacer las cosas al modo de Java vamos a crear una clase Persona
que vamos a estar instanciando para pasarla a través de los métodos en donde los datos se guardan.
No es obligatorio, pero es un buen paradigma. La clase queda así:
package me.parzibyte.agenda.modelos;
public class Persona {
private String nombre, telefono;
private int id;
public Persona(String nombre, String telefono, int id) {
this.nombre = nombre;
this.telefono = telefono;
this.id = id;
}
public Persona(String nombre, String telefono) {
this.nombre = nombre;
this.telefono = telefono;
}
public Persona() {
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getTelefono() {
return telefono;
}
public void setTelefono(String telefono) {
this.telefono = telefono;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Tiene sus getters y setters; los setters no están siendo utilizados pero los getters si. Eso es más que nada por el encapsulamiento, cosa que no tiene lugar en este post.
Debemos crear una clase que extienda de SQLiteOpenHelper
. Vamos a sobrescribir el constructor y los métodos onCreate
y onUpgrade
.
package me.parzibyte.agenda;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class ConexionSQLiteHelper extends SQLiteOpenHelper {
public ConexionSQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(Utilerias.CREAR_TABLA_PERSONA);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + Utilerias.TABLA_PERSONA);
onCreate(db);
}
}
El método onCreate
es llamado cuando la base de datos es creada por primera vez. Aquí se deberían crear las tablas y llenar los datos iniciales si son necesarios. Lo único que hacemos es crear la tabla.
El método onUpgrade
es cuando entregamos una nueva versión de la base de datos; en ese método modificamos las tablas o datos para realizar la actualización para los usuarios que ya tenían la base de datos instalada. Lo único que hacemos es eliminar la BD y volverla a crear.
Ahora veamos el primer paso de este crud: hacer un registro. Tenemos el layout en donde solicitamos:
Son 3 EditText y un Button. El layout queda así:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ActivityRegistrar">
<EditText
android:id="@+id/etIdentificador"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:ems="10"
android:hint="@string/identificador"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/etNombre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:ems="10"
android:hint="@string/nombre"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etIdentificador" />
<EditText
android:id="@+id/etTelefono"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:ems="10"
android:hint="@string/tel_fono"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etNombre" />
<Button
android:id="@+id/btnRegistrar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:hint="@string/guardar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etTelefono" />
</android.support.constraint.ConstraintLayout>
Al presionar el botón se debe generar un registro. Para hacerlo usamos ContentValues, le ponemos los valores obtenidos de los EditText; creamos una nueva instancia de la base de datos y hacemos el registro de la persona.
package me.parzibyte.agenda;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
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.Toast;
public class ActivityRegistrar extends AppCompatActivity {
private boolean existe(String id) {
ConexionSQLiteHelper conexion = new ConexionSQLiteHelper(ActivityRegistrar.this, Utilerias.NOMBRE_BD, null, 1);
SQLiteDatabase bd = conexion.getReadableDatabase();
String[] parametros = {id};
String[] campos = {Utilerias.CAMPO_NOMBRE};
Cursor cursor = bd.query(Utilerias.TABLA_PERSONA,
campos,
Utilerias.CAMPO_ID + "=?",
parametros,
null,
null,
null);
return cursor.moveToFirst();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_registrar);
final EditText etIdentificador = findViewById(R.id.etIdentificador),
etNombre = findViewById(R.id.etNombre),
etTelefono = findViewById(R.id.etTelefono);
Button btnRegistrar = findViewById(R.id.btnRegistrar);
btnRegistrar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String identificador = etIdentificador.getText().toString(),
nombre = etNombre.getText().toString(),
telefono = etTelefono.getText().toString();
if (existe(identificador)) {
Toast.makeText(ActivityRegistrar.this, "Identificador existente", Toast.LENGTH_SHORT).show();
return;
}
if (identificador.isEmpty() || nombre.isEmpty() || telefono.isEmpty()) return;
ContentValues contentValues = new ContentValues();
contentValues.put(Utilerias.CAMPO_ID, identificador);
contentValues.put(Utilerias.CAMPO_NOMBRE, nombre);
contentValues.put(Utilerias.CAMPO_TELEFONO, telefono);
ConexionSQLiteHelper conexion = new ConexionSQLiteHelper(ActivityRegistrar.this,
Utilerias.NOMBRE_BD, null, 1);
SQLiteDatabase bd = conexion.getWritableDatabase();
long respuesta = bd.insert(Utilerias.TABLA_PERSONA, null, contentValues);
Toast.makeText(ActivityRegistrar.this, "Registro #" + respuesta, Toast.LENGTH_SHORT).show();
bd.close();
}
});
}
}
Dentro del código también existe el método existe
, el cual recibe un identificador como cadena, hace una consulta y nos indica si un registro con determinado identificador ya está registrado.
Hacemos una simple validación con .isEmpty()
para ver si los datos están vacíos y también llamamos al método existe para evitar registros con ids duplicados.; después obtenemos la base de datos en modo escritura y llamamos al método insert
, el cual devuelve un tipo de dato long
indicando el row id del nuevo registro.
Mostramos el número de registro en un Toast y con eso queda.
La interfaz para consultar pide el identificador y rellena los EditText
con los datos traídos de la base de datos.
Si los datos existen, se rellenan los EditText
. Si no, se muestra un Toast
indicando que no existe.
El layout queda así:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ActivityConsultar">
<EditText
android:id="@+id/etIdBusqueda"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:ems="10"
android:hint="@string/id"
android:inputType="numberSigned"
app:layout_constraintEnd_toStartOf="@+id/btnBuscar"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnBuscar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="@string/buscar"
app:layout_constraintBaseline_toBaselineOf="@+id/etIdBusqueda"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/etIdBusqueda" />
<EditText
android:id="@+id/etMostrarNombre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:ems="10"
android:hint="@string/nombre"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etIdBusqueda" />
<EditText
android:id="@+id/etMostrarTelefono"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:ems="10"
android:hint="@string/tel_fono"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etMostrarNombre" />
</android.support.constraint.ConstraintLayout>
Definimos lo que se ve en la imagen. El código Java para escuchar el click del botón, buscar el registro y poner los datos en el EditText queda así:
package me.parzibyte.agenda;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
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.Toast;
public class ActivityConsultar extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_consultar);
final EditText etIdBusqueda = findViewById(R.id.etIdBusqueda),
etMostrarNombre = findViewById(R.id.etMostrarNombre),
etMostrarTelefono = findViewById(R.id.etMostrarTelefono);
Button btnBuscar = findViewById(R.id.btnBuscar);
btnBuscar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String idBusqueda = etIdBusqueda.getText().toString();
if (idBusqueda.isEmpty()) return;
ConexionSQLiteHelper conexion = new ConexionSQLiteHelper(ActivityConsultar.this, Utilerias.NOMBRE_BD, null, 1);
SQLiteDatabase bd = conexion.getReadableDatabase();
String[] parametros = {idBusqueda};
String[] campos = {Utilerias.CAMPO_NOMBRE, Utilerias.CAMPO_TELEFONO};
Cursor cursor = bd.query(Utilerias.TABLA_PERSONA,
campos,
Utilerias.CAMPO_ID + "=?",
parametros,
null,
null,
null);
if (!cursor.moveToFirst()) {
Toast.makeText(ActivityConsultar.this, "ID Inexistente", Toast.LENGTH_SHORT).show();
etMostrarNombre.setText("");
etMostrarTelefono.setText("");
bd.close();
return;
}
etMostrarNombre.setText(cursor.getString(cursor.getColumnIndex(Utilerias.CAMPO_NOMBRE)));
etMostrarTelefono.setText(cursor.getString(cursor.getColumnIndex(Utilerias.CAMPO_TELEFONO)));
}
});
}
}
Nuevamente usamos a Toast para indicar los mensajes. Ahora llamamos al método query
que devuelve un cursor (como en la función para comprobar si el identificador ya existía) y buscamos los datos en donde el id sea igual al proporcionado.
Por cierto, ahora no queremos la base de datos en modo escritura; solo lectura.
En caso de que haya datos obtenemos a los mismos con cursor.getString
, pasándole el índice de la columna que, para no equivocarnos, obtenemos con getColumnIndex
.
Para terminar el ejercicio veamos la forma de listar los datos de la agenda. Esto es un poco más complejo porque involucra un RecyclerView y un adaptador para el mismo. además del diseño de un layout para cada fila y algunos otros métodos.
La lista debe mostrar el id, el número de teléfono y el nombre de la persona.
Para empezar definimos el layout que tendrá el RecyclerView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ActivityListar">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerViewPersonas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
El RecyclerView mostrará filas. La fila individual queda así:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:padding="5dp">
<TextView
android:id="@+id/tvFilaNombre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:text="Nombre"
android:textColor="@color/colorPrimaryDark"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvFilaEdad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:text="Teléfono"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvFilaNombre" />
<TextView
android:id="@+id/tvFilaIdentificador"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:text="TextView"
android:textColor="@color/colorAccent"
app:layout_constraintBaseline_toBaselineOf="@+id/tvFilaNombre"
app:layout_constraintStart_toEndOf="@+id/tvFilaNombre"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
El adaptador que se encarga de poner los datos de la persona en la fila es el siguiente:
package me.parzibyte.agenda;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import me.parzibyte.agenda.modelos.Persona;
public class AdaptadorPersonas extends RecyclerView.Adapter<AdaptadorPersonas.MyViewHolder> {
private List<Persona> listaDePersonas;
public List<Persona> getListaDePersonas() {
return listaDePersonas;
}
public void setListaDePersonas(List<Persona> listaDePersonas) {
this.listaDePersonas = listaDePersonas;
}
public AdaptadorPersonas(List<Persona> listaDePersonas) {
this.listaDePersonas = listaDePersonas;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View filaPersona = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fila_persona, viewGroup, false);
return new MyViewHolder(filaPersona);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
// Obtener la persona de nuestra lista gracias al índice i
Persona persona = listaDePersonas.get(i);
// Obtener los datos de la lista
String nombre = persona.getNombre();
String telefono = persona.getTelefono();
String identificador = String.valueOf(persona.getId());
// Y poner a los TextView los datos con setText
myViewHolder.tvNombre.setText(nombre);
myViewHolder.tvEdad.setText(telefono);
myViewHolder.tvIdentificador.setText(identificador);
}
@Override
public int getItemCount() {
return listaDePersonas.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvNombre, tvEdad, tvIdentificador;
MyViewHolder(View itemView) {
super(itemView);
this.tvNombre = itemView.findViewById(R.id.tvFilaNombre);
this.tvEdad = itemView.findViewById(R.id.tvFilaEdad);
this.tvIdentificador = itemView.findViewById(R.id.tvFilaIdentificador);
}
}
}
De modo general está obteniendo la fila y poniendo cada valor en su posición de la fila; es decir, cada valor en un EditText
. Ese método será llamado por cada fila del RecyclerView
.
También definimos el constructor en donde vamos a estar trabajando con una lista (List
) de tipo Persona
para saber a cuál persona dibujar en determino lugar.
Finalmente la actividad que obtiene la lista de personas y la pone al adaptador para el RecyclerView es la siguiente:
package me.parzibyte.agenda;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import me.parzibyte.agenda.modelos.Persona;
public class ActivityListar extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listar);
RecyclerView recyclerView = findViewById(R.id.recyclerViewPersonas);
ConexionSQLiteHelper conexion = new ConexionSQLiteHelper(ActivityListar.this, Utilerias.NOMBRE_BD, null, 1);
SQLiteDatabase bd = conexion.getReadableDatabase();
String[] campos = {Utilerias.CAMPO_NOMBRE, Utilerias.CAMPO_TELEFONO, Utilerias.CAMPO_ID};
Cursor cursor = bd.query(Utilerias.TABLA_PERSONA,
campos,
null,
null,
null,
null,
null);
if (!cursor.moveToFirst()) {
cursor.close();
bd.close();
return;
}
ArrayList<Persona> personas = new ArrayList<>();
do {
String nombre = cursor.getString(cursor.getColumnIndex(Utilerias.CAMPO_NOMBRE));
String telefono = cursor.getString(cursor.getColumnIndex(Utilerias.CAMPO_TELEFONO));
int id = cursor.getInt(cursor.getColumnIndex(Utilerias.CAMPO_ID));
Persona persona = new Persona(nombre, telefono, id);
personas.add(persona);
} while (cursor.moveToNext());
// Fin del ciclo. Cerramos cursor y regresamos la lista de mascotas :)
cursor.close();
AdaptadorPersonas adaptadorPersonas = new AdaptadorPersonas(personas);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adaptadorPersonas);
}
}
Iteramos el cursor y vamos agregando un elemento al ArrayList
. El momento en donde la magia ocurre es cuando llamamos a setAdapter
; los demás métodos que tienen que ver con el RecyclerView
son para agregar algunos diseños.
Con este ejercicio reforzamos un poco más los métodos que Android ofrece para trabajar con bases de datos. Como lo dije al inicio, si quieres uno más avanzado mira el CRUD de Mascotas.
Todo el código que se necesita está en GitHub en el link que puse al inicio.
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Ayer estaba editando unos archivos que son servidos con el servidor Apache y al visitarlos…
Esta web usa cookies.
Ver comentarios
Hola en este ejemplo no entendí que editor de texto usaste para escribir el código y que dispositivo usaste una computadora o un dispositivo móvil? Espero tu respuesta saludos