To Do list con Firebase y Android

Firebase

Firebase es una plataforma de backend para construir aplicaciones móviles y web, se encarga del manejo de la infraestructura permitiendo que el desarrollador se enfoque en otros aspectos de la aplicación. Entre sus características se incluye base de datos de tiempo real, autenticación de usuarios y almacenamiento(hosting) estático. La idea de usar Firebase es no tener que escribir código del lado del servidor y aprovechar al máximo las características que nos provee la plataforma.

Para utilizar Firebase con Android disponemos de un SDK, lo que nos permitirá integrarlo fácilmente a nuestra aplicación. Para este ejemplo vamos a construir un listado de cosas por hacer usando la base de datos de tiempo real de Firebase como backend y autenticación con email/password y Twitter. El contenido se divide en tres partes, en la primera vimos lo básico, en esta segunda parte de la guía haremos un app de un listado de cosas por hacer sin ninguna autenticación

Android

El primer paso es crear un proyecto, si tienes dudas, puedes ir a ver la primera parte de esta guía. Queremos que al terminar, el app se vea algo así

Diseño

Tendremos una única pantalla y en esta dos elementos clave: un listado y una forma de ingreso de datos. Para el listado haremos uso de un RecyclerView y para el ingreso de datos un EditText envuelto por un TextInputLayout que es parte de la librería de Material Design y permitirá mostrar el hint como un texto flotante. Por último, haremos uso de un FloatingActionButton para el envío de los datos. Todos estos elementos bajo el orden que impone un RelativeLayout.

Para complementar el uso del RecyclerView, vamos a especificar a través de un layout personalizado el contenido de cada una de las filas del listado.

El elemento más alto en la jerarquía será un LinearLayout con configuración horizontal, dentro del mismo tendremos otro LinearLayout pero este organizado de forma vertical para mostrar el texto de los elementos del listado y al lado derecho un ImageView con un ícono que denotará que la tarea ha sido concluída.

Cada elemento del listado tendrá dos líneas de texto, una de texto grande para indicar la tarea y otra de texto mediano para indicar el nombre del usuario que agregó la tarea.

Application Class

Haremos uso de una clase que herede de Application para poder inicializar todo lo que necesitamos. En esta clase tendremos la referencia a Firebase y en el método onCreate asignamos todo lo necesario. Agregamos una llamada a setPersistenceEnable con parámetro true para tener soporte offline y que aun que no haya conexión todo se guarde forma local y cuando se disponga de conexión se envíe al backend. Por último, agregamos un getter para obtener la referencia a Firebase en donde la necesitemos.

Modelo de datos

Vamos a representar cada uno de los elementos del listado de cosas por hacer con un POJO que se traducirá a JSON para ser almacenado en Firebase y viceversa al recibirlo de la base de datos.

Llamaremos ToDoItem a este modelo y tendrá tres campos: username(nombre del usuario que creó el elemento), item(elemento del listado de cosas por hacer) y completed(si el elemento ha sido completado o no). Acompañando a estas variables, vamos a crear getters y setters para obtener y modificar los valores asociados.

Manejo de usuarios

Disponemos de un listado colaborativo, por lo mismo es buena idea identificar al usuario que está creando elementos. Para ello, obtenemos un número aleatorio la primera vez que el usuarioa accede al app y guardamos el nombre de usuario asignado en el diccionario de SharedPreferences. El código para la configuración del nombre de usuario lo colocamos en la actividad principal (MainActivity.java)

Inicialización en actividad principal

Continuamos trabajando en la actividad principal (MainActivity.java) y allí definimos dos variables con anotación de ButterKnife para el listado (RecyclerView) y para el texto que ingresará el usuario (EditText), con la anotación hacemos el vínculo a la vista.

Además, definimos como variable global la referencia a Firebase (que vamos a obtener del application class), el adaptador(FirebaseRecyclerViewAdapter) para el listado que hará uso de Firebase-UI y un listener(ChildEventListener) para los eventos que se generan al modificar los datos del listado.

En el método onCreate de la actividad realizamos la inicialización de variables necesaria después de la llamada al ancestro (super.onCreate) y de asignarle el layout de la vista correspondiente pasamos a inicializar ButterKnife para el vínculo con la vista. Posterior a esto, se llama al método de configuración de nombre de usuario y lo colocamos en el ActionBar. Por último obtenemos la referencia a Firebase desde el application class y lo asignamos a la variable previamente definida.

Manejo de elementos.

Para agregar elementos nuevos al listado, requerimos de construir todo lo necesario para el RecyclerView en el que se van a mostrar. El primer pasó será crear un ViewHolder que contenga los tres elementos definidos en el diseño de cada fila del listado. Para esto, nos apoyamos en heradar de RecyclerView.ViewHolder y en el vínculo(binding) de la vista con ButterKnife. Todo esto en una clase interna, definida al final del mismo archivo de nuestra actividad principal.

A continuación volvemos al método onCreate e inicializamos el adaptador. Firebase-UI nos facilita el proceso en buenta parte y solo es necesario enviar algunos parámetros. Indicamos que el adaptador hará uso de los tipos de datos de nuestro modelo (ToDoItem) y view holder (ToDoItemViewHolder) y como parámetros se envían la clase del modelo, el layout de la fila de cada elemento, la clase del view holder y la referencia a Firebase para obtener los datos.

Vamos a sobrecargar dos métodos dentro de esta implementacióndel RecyclerView: populateViewHolder y onCreateViewHolder. El primero para asignar los valores a mostrarse y en caso de que el elemento ya haya sido completado mostrar el ícono que indica esto.

El segundo es requerido por el manejo de click en cada elemento (que implementaremos más adelante) y se debe a que FirebaseRecyclerViewAdapter espera que la clase del view holder sea interna y estática. Se recomienda que la clase del view holder sea estática si se re-utilizará para algún otro adaptador sin embargo como esta clase no debe salir del contexto de esta actividad no debería haber problema con que no sea estática aun que consuma un poco más de memoria. Nos interesa que no sea estática para poder hacer uso de métodos no-estáticos en el manejo del click.

Por último asignamos el LayoutManager y el adaptador para el listado.

Con todo esto listo, podemos proceder a agregar elementos cuando se haga click sobre el FAB (FloatingActionButton). Cuando se de este click, obtenemos desde SharedPreferences el nombre del usuario, desde el EditText el texto ingresado y por defecto no será una tarea concluída. Adicional a eso limpiamos el texto y ocultamos el teclado.

Y así de fácil, hakuna matata, tenemos listo el manejo de los datos. Si algún elemento es modificado o eliminado del backend también lo será en nuestro listado :D

Firebase-UI hace el heavy lifting por nosotros, no necesitamos hacer uso de ningún listener sin embargo si queremos realizar alguna acción asociada a los eventos, podemos hacerlo con algún listener. Agregaremos un ChildEventListener que nos permitirá hacer scroll del listado al agregar nuevos elementos de tal forma que siempre se vean los elementos más nuevos que quedan al final de la lista. Esto lo hacemos en el método onChildAdded que se ejecuta al tener un elemento nuevo, local o remoto.

Modificando y eliminando elementos

RecyclerView introdujo varios cambios respecto a como hacíamos las cosas con ListView, entre ellos que ya no hay un soporte para clicks en esta vista. Hay varias formas de implementarlo pero generalmente se hace en el ViewHolder.

Para implementarlo, modificaremos la clase del ViewHolder agregando que implemente las interfaces View.OnClickListener y View.OnLongClickListener además de indicar en el constructor que la misma clase (this) será encargada de manejar click y click largo de la vista recibida.

La idea es que vamos a modificar elementos con un click, cambiando su estado a la alternativa, es decir si se encuentra pendiente de completar lo colocamos como terminado y si está terminado al recibir un click lo colocamos como pendiente.

Dentro de la misma clase del view holder, sobrecargamos el método onClick y obtenemos la posición haciendo uso de getAdapterPosition, con esta posición obtenemos el elemento del adaptador y modificamos si ha sido completado o no. para realizar la actualización con Firebase colocamos el nuevo valor en un diccionario y llamamos a updateChildren con el diccionario de parámetro y sobre la referencia directa del elemento. Esta referencia la obtenemos del adaptador con la posición sobre la que se hizo click

Por último, vamos a eliminar elementos con un click largo, entonces sobrecargamos onLongClick y en este método obtenemos la referencia de este elemento de parte del adaptador tal como lo hicimos en el caso anterior, usando getRef y getAdapterPosition de parámetro. De esta referencia, llamamos a removeValue y listo, el elemento ha sido eliminado.

Con esto hemos terminado nuestra aplicación de listado de cosas por hacer.

Conclusiones

En esta guía hemos aprendido sobre como usar Firebase y Firebase-UI, para agregar, editar y eliminar elementos construyendo una aplicación colaborativa de listado de cosas por hacer(To Do), al igual que el caso anterior, el código que hemos escrito es totalmente del lado del cliente. El proyecto está disponible en Github.

En la siguiente entrega vamos a agregarle soporte de autenticación con email/password y Twitter usando el SDK de Fabric.