Guia Android: Avanzando con la base de datos
Creando la nota con el formulario Lo que queremos ahora es que cuando hacemos click en Add Item vayamos a otra pantalla donde podamos escribir el título y el texto de la nota. Demos a guardar y aparezca en la lista de notas. Para eso vamos a tener que crear otra actividad (pantalla-controlador). Pensad que por cada pantalla que queramos tener vamos a tener que tener una nueva actividad.
Creando la nota con el formulario
Antes de eso vamos a permitir borrar notas, para ello vamos a Notas.java. Añadimos la siguiente línea al final del método onCreate()
registerForContextMenu(getListView());
Queremos que al hacer click en un elemento de lista nos salga un menú desde donde podamos borrarlo. Añadimos un nuevo método que sobreescribe a uno de Android:
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add(0, DELETE_ID, 0, R.string.menu_delete); }
Hace falta insertar más variables en Notas.java
private static final int ACTIVITY_CREATE=0; private static final int ACTIVITY_EDIT=1; private static final int INSERT_ID = Menu.FIRST; private static final int DELETE_ID = Menu.FIRST + 1;
y en strings.xml
<string name="menu_delete">Delete Note</string> <string name="title">Title</string> <string name="body">Body</string> <string name="confirm">Confirm</string> <string name="edit_note">Edit Note</string>
Ahora que ya podemos seleccionar la nota a borrar, vamos a crear el método que efectivamente lo borra:
@Override public boolean onContextItemSelected(MenuItem item) { switch(item.getItemId()) { case DELETE_ID: AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); mDbHelper.deleteNote(info.id); fillData(); return true; } return super.onContextItemSelected(item); }
Volvemos a hacer un switch para comprobar la posición del botón del menú y si es la segunda borramos la nota y recargamos la lista. Conseguimos el ID de la nota gracias a getMenuInfo() y al método registerForContextMenu() que hemos insertado antes al final de onCreate().
Volvamos ahora al método auxiliar para crear nuevas notas, borramos lo que teníamos y vamos a cargar una nueva actividad:
private void createNote() { Intent i = new Intent(this, NoteEdit.class); startActivityForResult(i, ACTIVITY_CREATE); }
Lo que hacemos es crear un nuevo Intent, una nueva actividad, en este caso NoteEdit que todavía no hemos creado. Ejecuta su comienzo y espera el resultado. Con el resultado luego llamará a la función onActivityResult() que implementaremos más tarde. Si no nos interesa saber el resultado basta con llamar a la función startActivity()
Vamos a hacer algo parecido para editar las notas que ya tenemos. Pero antes de nada vamos a permitir utilizar el Cursor en toda la clase, para eso añadimos la variable de clase:
private Cursor mNotesCursor;
refactorizamos onCreate() que quedaría ahora así:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.notepad_list); mDbHelper = new NotasDbAdapter(this); mDbHelper.open(); fillData(); registerForContextMenu(getListView()); }
y nuestro método privado fillData()
private void fillData() { // Recupera todas las notas de la DB y las guarda en el cursor mNotesCursor = mDbHelper.fetchAllNotes(); startManagingCursor(mNotesCursor); // Array con los campos que queremos mostrar en la lista String[] from = new String[]{NotasDbAdapter.KEY_TITLE}; // array con las variables asociadas para esos campos int[] to = new int[]{R.id.text1}; SimpleCursorAdapter notes = new SimpleCursorAdapter(this, R.layout.notes_row, mNotesCursor, from, to); setListAdapter(notes); }
Ahora ya podemos fijarnos en el método que se ejecute al hacer click sobre un elemento de la lista. Se llama onListItemClick() y lo sobreescribimos:
@Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Cursor c = mNotesCursor; c.moveToPosition(position); Intent i = new Intent(this, NoteEdit.class); i.putExtra(NotasDbAdapter.KEY_ROWID, id); i.putExtra(NotasDbAdapter.KEY_TITLE, c.getString( c.getColumnIndexOrThrow(NotasDbAdapter.KEY_TITLE))); i.putExtra(NotasDbAdapter.KEY_BODY, c.getString( c.getColumnIndexOrThrow(NotasDbAdapter.KEY_BODY))); startActivityForResult(i, ACTIVITY_EDIT); }
Lo que estamos haciendo es mover el Cursor a la posición en la que estamos, crear el Intent y pasarle como argumentos el Id, título y texto. Para pasar como argumentos utilizamos la función putExtra(). Otra función muy útil. Por último lo ejecutamos esperando el resultado.
Va siendo hora de implementar el método onActivityResult() que es el que se ejecuta cuando recibimos el resultado de haber creado o editado una nota con startActivityForResult()
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); Bundle extras = intent.getExtras(); switch(requestCode) { case ACTIVITY_CREATE: String title = extras.getString(NotasDbAdapter.KEY_TITLE); String body = extras.getString(NotasDbAdapter.KEY_BODY); mDbHelper.createNote(title, body); fillData(); break; case ACTIVITY_EDIT: Long mRowId = extras.getLong(NotasDbAdapter.KEY_ROWID); if (mRowId != null) { String editTitle = extras.getString(NotasDbAdapter.KEY_TITLE); String editBody = extras.getString(NotasDbAdapter.KEY_BODY); mDbHelper.updateNote(mRowId, editTitle, editBody); } fillData(); break; } }
Si estamos creando la nota, la guarda en la base de datos. Si la estamos editando, la actualiza y en ambos casos recarga la lista de notas.
Ya tenemos la lógica más o menos, vamos ahora a crear el layout del formulario. Para eso creamos el archivo /res/layout/note_edit.xml y lo rellenamos con:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/title" /> <EditText android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1"/> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/body" /> <EditText android:id="@+id/body" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:scrollbars="vertical" /> <Button android:id="@+id/confirm" android:text="@string/confirm" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
Este es un layout ya más complicado. Lo que hace es crear dos campos de texto, uno para el título y otro para el texto; y el botón que guarda lo que hemos escrito. Utilizando una mezcla de configuraciones de alturas conseguimos la apariencia que queremos. En el próximo tutorial entraremos más en detalle en los layouts.
Vamos a crear la clase NoteEdit.java ahora que ya tenemos su layout. Voy a copiar el código final comentado y explico detalles al final:
/* * Copyright (C) 2008 Google Inc. */ package com.android.demo.notepad1; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; public class NoteEdit extends Activity { private EditText mTitleText; private EditText mBodyText; private Long mRowId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Fijamos el layout de esta actividad setContentView(R.layout.note_edit); // Objetos que referencian a los campos editables del layout mTitleText = (EditText) findViewById(R.id.title); mBodyText = (EditText) findViewById(R.id.body); Button confirmButton = (Button) findViewById(R.id.confirm); // Si hay argumentos, los cogemos mRowId = null; Bundle extras = getIntent().getExtras(); if (extras != null) { String title = extras.getString(NotasDbAdapter.KEY_TITLE); String body = extras.getString(NotasDbAdapter.KEY_BODY); mRowId = extras.getLong(NotasDbAdapter.KEY_ROWID); // Insertamos los valores actuales de la nota en los campos if (title != null) { mTitleText.setText(title); } if (body != null) { mBodyText.setText(body); } } // Listener para el botón de confirmar confirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Bundle bundle = new Bundle(); // Guardamos los nuevos valores en un Bundle bundle.putString(NotasDbAdapter.KEY_TITLE, mTitleText.getText().toString()); bundle.putString(NotasDbAdapter.KEY_BODY, mBodyText.getText().toString()); if (mRowId != null) { bundle.putLong(NotasDbAdapter.KEY_ROWID, mRowId); } // y los mandamos de vuelta al método que los está esperando Intent mIntent = new Intent(); mIntent.putExtras(bundle); setResult(RESULT_OK, mIntent); finish(); } }); } }
Hay que fijarse en cómo cogemos la referencia al campo de texto (mediante la clase R.java por supuesto)
mTitleText = (EditText) findViewById(R.id.title);
En cómo cogemos los argumentos que hemos pasado antes con el método putExtra()
y cómo asignamos los valores actuales
mTitleText.setText(title);
El último paso tras crear una nueva actividad es declararla en el archivo AndroidManifest.xml. Recordarlo bien porque es un típico fallo que nos hace perder muchas horas.
<activity android:name=".NoteEdit"></activity>
También se puede introducir la nueva actividad con los paneles de control en vez de directamente sobre el código (Application -> Add Application Node -> Activity y rellenamos el nombre)
Es hora de ejecutar el programa de nuevo para ir viendo cómo evoluciona. Ya podemos editar las notas que creamos antes y crear nuevas con la opción Add Item del menú. Probad a dar hacia atrás cuando estéis en el formulario. Veréis cómo salta una excepción.
Resumen
Hoy hemos tocado muchos temas y muy variados:
- Hemos creado nuestro primer modelo con su conexión a la base de datos (adaptador de por medio para facilitarnos la vida).
- Hemos visto más layouts para mostrar listas y formularios.
- Hemos creado una actividad de lista que os puede servir de modelo para vuestras apps. Permite crear nuevas notas, editarlas y borrarlas. Aunque mejor esperad a la semana que viene para tomarla como modelo ya que haremos algunos cambios importantes.
- Hemos creado una segunda actividad por lo que ya podemos decir que nuestra app es medianamente compleja, al menos tiene 2 pantallas!
El próximo día arreglaremos los pequeños fallos que nos hemos dejado, mejoraremos el código para hacerlo más óptimo, y aprenderemos muchas más vistas en otros ejemplos, como por ejemplo cómo mostrar tu posición en el mapa. Por hoy creo que es suficiente. Repasad el tutorial, ved la API de Android y si tenéis alguna duda preguntad en Foros del Web o en los comentarios de esta entrada e intentaré responder.
[…] Avanzando en Android con la base de datos […]
[…] han publicado en Maestros del Web un interesante tutorial para aprender a trabajar con Bases de Datos en […]
Muy bueno y muy completo. Voy a ver si me sale. Sigo con afan tus tutoriales. Gracias
Lo tengo que probar, y mis felicitaciones por esta iniciativa.
Animo y saludos.
muchas gracias a los 2! Ya me contaréis como os va
Creo que de este tutorial al anterior hay un salto demasiado grande para los que no tenemos mucha idea podamos pillarlo.
Creo que sería interesante ir algo más despacio. Simplemente primero creando botones y darles utilidad, añadir listas y darles utilidad, etc… e incluso coger la aplicación Hola Mundo y que vaya mejorando y vaya sirviendo para cosas y podamos ver cada cosa para que sirve.
En fin, es solo una opinión.
Tal vez tu idea es ir algo más rápido y centrarte más en la gente que tiene algo de nivel en la programación en general.
Saludos y gracias.
[…] Siguiendo con Android, la segunda parte del tutorial para crear aplicaciones de la gente de Maestros del Web (que por cierto hoy están cumpliendo 12 años – que en la web es algo así como el equivalente a un eon – ¡feliz cumpleaños!). Link. […]
Huy, por fin algo en serio en nuestro idioma!
Muchas gracias viejo te invito a seguir con esto! Ya tengo todo instalado y configurado. Lei la primera introduccion y palpe esta asi que ma;ana me pongo a seguir este curso y te cuento. Seguramente tendre muchas cosas que preguntar….
Saludos 😉
Muchas gracias,
Me ha servido mucho para entender el funcionamiento de Android.
Estaria mas que bueno que hicieras un video, ya que es complicado seguir los pasos de este modo.. Tengo 15 años y la verdad que no entiendo un pepino, recien acabo de hacer la app que dice el nombre de la aplicacion, le cambie la imagen apra que aparesca en el menu, y le agregue un texto abajo.. Por favvor necesito ayuda muchas Gracias!.
Muchas gracias, espero que tengas exito en tu master, abrazo desde Buenos Aires
Excelente tutorial! después de muchos intentos, con este tutorial pude tener una base de datos “comunitaria” que la pueden compartir todas las Actividades!
Muchas Gracias! 😀
No puedo importar tu proyecto. Se me junta que soy nuevo en eclipse y en android.
Project has no default.properties file! Edit the project properties to set one.
Tengo Eclipse IDE for Java Developers Version: Helios Service Release 1
s2
Bueno solucione mi problema. Borre el R.java y refactorice dandole otro nombre. FuerzaBruta.com
Hola, sería bueno que continuara ésta guía hace tiempo que no escriben más sobre desarrollo en Android.
esto sirve para una base de datos MySQL?
Buenos días, me parece excelente su tutorial, pero tengo una pregunta, la variable o metodo “mDB” en donde la instancia???
Gracias.