ADAFramework: How to work with relationships

In this post I’m going to talk about ADA Framework again, specifically about how to work with relationships. I’ve tried to publish it as soon as it was possible but It tooks me more than I thought because, as you can see, I decided to write it in English ;).

Well! Let’s begin at the biginning! 😉

Sources:

Development envirnomment information:

  • Windows 7 Home Premium 64bits.
  • Eclipse Indigo and ADT Plugin for Eclipse.
  • Android SDk 2.2 (min. sdk 8).
  • ADA Framework 1.4.5.
  • Tested on Samsung Galaxy ACE GT-S5830 con Android 2.3.5
  • SVN repository download: svn://svn.code.sf.net/p/rateyourmusic/code-0/trunk

Project package explorer:

In this case I’ve created an Android project related to music and to song rates. I’ve defined two concepts:

1.- We are going to work with two entities call Song and Album.

2.- One Song is linked to on Album neither one Album is linked to many Songs.

ADA Framework make our work with our relationships easier because we now we only have to give an Album entity to our Song entity. Look at this code:

The first one ir Song class and the second one is Album class and both extend from com.desandroid.framework.ada.Entity like always. As you can see we have defined our relationship using the “album” attribute of Album type and we have defined it as Entity.DATATYPE_ENTITY_REFERENCE. Now we can to start to work with our entities.

Like in previous post, we are going to create an entity manager that allows to work get information from database and to save, to update and to delete (CRUD operationes) data in database. This is ApplicationDataContext and it extends to com.desandroid.framework.ada.ObjectContext. Let’s see a bit of code:

It’s simple, isn’t it?. Look at the first piece of code. it contains two com.desandroid.framework.ada.ObjectSet attributes to manage our two entity types. They allows us to execute all CRUD operation wich ObjectSet class contains. Now, when we create a ApplicationDataContext instance ir our Activities we will have two structures to do INSERT, UPDATE, DELETE and SELECT (basic and complex) operations with Songs and Albums, and when we won’t do anything special if we will go to save a song with a album or a position or a name, that’s the same.

Now we are going to talk about Activity classes in the project. I’ve created two activities.

1.- HomeActivity: Allows to list all songs with this format: POSITION .- SONG NAME (RATING) .

2.- SongDetails: Allows to create a new activity or to vote for songs.

I’m going to talk only about the most important in this classes, but if you have doubts, suggestions or corrections you just write your comment ;).

As we haven’t songs and albums initially, when we run the frrist time it found that database is empty and makes several songs and albums and their relationships. For next times load ones and it doesn’t create again.

* Take a loot at initializedDatabase() method in project source code if you don’t understand what it does.

As you can see, HomeActivity is our ListView component to show songs and it contains an ArrayAdapter to magane songs and to put into the ListView. Too, it have an ApplicationDataContext attribute to get songs from database executing dataContext.getSongSet().fill() line code.

At the end of onCreate method we define the same adapter for song records in database and in ListView. Yes! This seems weird but is the way to define the relationship between database and Activity classes.

What happen when I do click in a lisview item?… Well it shows you detailed information about that item (Song) that allows you to vote for songs.

We have two options, as I said, vote for a song (onListItemClick overrided method) or, if you want to create a new song, press your menu device menu button (onOptionItemSelected overrided method). In the second one you can see that we passing parameters bettween Activities with intent.putExtra(ARGUMENT_NAME,ARGUMENT_VALUE), with SONG_ID. It allows to find this song in database to load it in SongDetails Activity.

One more thing about HomeActivity class! To refresh that ListView when we update it I’ve overrided onResume method, and I’d like to know your opinion about that. Do you know another ways to do that? How do you usually do that?

Now we are going to look at SongDetails Activity.

SongDetails activity detects if we want to create or not to create a song checking if we have passed SONG_ID parameter from HomeActivity.

If we want to create a song, we load albums from database into Spinner component (loadAlbumsSpinner method) and set form field as Editable state:

Press on album spinner:

Else, we search in database the song clicked in HomeActivity ListView and load her detailed information (loadInformation method) :

Finally when we do click in vote button vote method is executed:

And it execute one of two queries using the same method dataContext.getSongsSet().save(SONG_OBJECT):

1.- INSERT INTO ‘tSong’: Put  attention on  song.setAlbum((Album) spinner.getSelecteditem())!! We are creating our relashionship between Song and Album as if only was a simple data type like String, int, boolean, etc. 

2.- UPDATE TABLE ‘tSong’: Put attention on song.setStatus.(Entity.STATUS_UPDATED), because if you don’t change that property ADA Framework won’t do anything and your changes won’t be saved.

Fill the form and press on vote spinner:



Now it’s your turn! Press device menu button whe you are showing any song details 😉

My most sincere thanks for @DesAndrOId

Anuncios
Publicado en Android | Etiquetado , , , , | 4 comentarios

Uso básico de ADA Framework: Parte II

Continuando con el proyecto del que hablamos en la entrada Uso básico de ADA Framework: Parte I pasamos ahora a realizar una muestra de como ver los datos almacenados en la base de datos en la pantalla de nuestra aplicación.

Entorno de desarrollo:

  • Windows 7 Home Premium 64bits.
  • Eclipse Indigo con ADT Plugin for Eclipse instalado.
  • Android SDk 2.2 (min. sdk 8).
  • ADA Framework 1.4.5.
  • Probado en Samsung Galaxy ACE GT-S5830 con Android 2.3.3
  • El repositorio de SVN para descargar el proyecto (Parte I yParte II) es: svn://svn.code.sf.net/p/adalab1/code/trunk (Es un único proyecto)

Fuentes:

Lo primero que vamos a hacer es modificar nuestro ApplicationDataContext para que NO sobreescriba el ObjectSet cada vez que se invoque su constructor (también podríamos utilizar el patrón de diseño Singleton pero no vamos a complicar más el código).

Ahora vamos a sobreescribir el método toString() de nuestra clase User para que al mostrar un elementoen la lista no aparezca el valor por defecto que devuelve este método sino, por ejemplonombre (email@email.com).

Y por último, antes de meternos a ver cómo se cargan los datos con ADA Framework, añadimos un ListActivity (que he llamado MainListActivity) donde cargaremos nuestra lista de usuarios y su layout (que he llamado main_list_item.xml) correspondiente que representa el layout de cada uno de los elementos representados en la vista.

Ahora toca analizar un poco el código aunque si nos fijamos bien, prácticamente todo es original de Android, exceptuando 2 o 3 líneas en las que el ApplicationDataContext carga los datos. Describo rápidamente los pasos:

  1. Declarar un ApplicationDataContext para interactuar contra la BD.
  2. Instanciar nuestro ApplicationDataContext, esto es en el código, new ApplicationDataContext(this);
  3. Cargar los datos de la base de datos en el ObjectSet del ApplicationData context, es decir, dataContext.getUsuarioSet().fill();
  4. Asignar el mismo Adapter de nuestro ListView que muestra los datos por pantalla, a nuestro manejador de datos de usuario del ApplicationDataContext, con dataContext.getUsuariosSet().setAdapter(…);

Como nota importante indicar que el método que hemos utilizado para la carga de los datos desde la BD en el ObjectSet (fill()) es una de las múltiples posibilidades. Este método hará que se ejecute la siguiente sentencia SQL que aparecerá en vuestro LogCat de Eclipse:

Como véis es un SELECT de todos los campos de la tabla sin ningún tipo de filtrado y con la ordenación por defecto por el campo ID de la tabla.

Otras posibilidades las podéis encontrar haciendo CTRL+SPACE después de getUsuarioSet(). y os aparecerá el listado de métodos que también podéis encontrar en la documentación de ObjectSet:

Este es el resultado del listado de usuarios del ejercicio:

Y esto es todo! En el próximo post acerca de ADA Framework trataré de explicaros como evolucionar este ejercicio para utilizar los Databinders para agilizar la carga de los datos desde la capa de persistencia en la de interfaz de usuario y viceversa.

Publicado en Android | Etiquetado , , , , | Deja un comentario

Uso básico de ADA Framework: Parte I

Como os comenté en la última entrada, aquí traigo un ejemplo de cómo funciona este maravilloso framework de persistencia para aplicaciones Android. Como os digo, esto es solo un ejemplo con el que empezar a investigar las posibilidades que nos brinda el ADA Framework, por lo que no todo queda aquí.

Entorno de desarrollo:

  • Windows 7 Home Premium 64bits.
  • Eclipse Indigo con ADT Plugin for Eclipse instalado.
  • Android SDk 2.2 (min. sdk 8).
  • ADA Framework 1.4.5.
  • Probado en Samsung Galaxy ACE GT-S5830 con Android 2.3.3
  • El repositorio de SVN para descargar el proyecto (Parte I yParte II) es: svn://svn.code.sf.net/p/adalab1/code/trunk

A continuación pasamos a la construcción del proyecto Android desde nuestro IDE Eclipse. Para ello en File > New > Android Project podemos indicar los datos de nuestro proyecto:

A continuación añadimos el .jar de la dependencia d ADA Framework al proyecto. Para ello vamos a crearnos una carpeta libs en el directorio raíz del proyecto donde suelo colgar las dependencias de terceros que empleo en las aplicaciones. Por lo tanto, la estructura de nuestro proyecto inicial debe tener un aspecto similar a este:

Donde como se ve, se ha añadido la mencionada carpeta libs y la dependencia del framework: com.desandroid.framework.ada_v1.4.5.jar.

Aquí podemos ya empezar a picar código que es lo que le gusta a los programadores, aunque siento decepcionaros porque , como ya he mencionado, ADA Framework facilita mucho el trabajo simplificando el código y por tanto esto todo muy mecánico a la hora de trabajar con él ;).

Lo primer que vamos a hacer es crear las dos clases que podríamos decir que en una aplicación que aplique el patrón de diseño MVC (modelo vista controlador) pueden localizarse en la parte del modelo y que están relacionadas con la persistencia de los datos en la base de datos. Estas clases son:

La primera clase la llamaremos User y debe extender de com.desandroid.framework.ada.Entity. Representa una entidad dentro de mi modelo entidad-relación en mi base de datos. Vamos a echar un vistazo al código para ver como mediante anotaciones podemos tener nuestra entidad definida sin tener que añadir los script de creación de tablas que se utilizan con android.database.sqlite:

si habéis utilizado algún framework de persistencia para desarrollar aplicaciones en otros entornos, puede que os sea familiar esta forma de trabajar. Por ejemplo si habéis utilizado Hibernate. Bueno! No tiene mucho que explicar porque es bastante intuitivo.

Si nos fijamos,  encima del nombre de la clase indicamos @Table(name = “tUser”) que quiere decir que la clase User representa la tabla tUser en nuestra base de datos. Y de igual forma podemos hacer esto con las columnas de la tabla utilizando la anotación @TableField(…) donde además podemos añadir propiedades como:

  • name = “[FIELD_NAME]” , donde FIELD_NAME es el nombre que va a tener la columna en la base de datos y que se correpsonderá con este atributo de la clase User
  • datatype = “[FIELD_DATATYPE]” , donde FIELD_DATATYPE es el tipo de la columna en la base de datos y para indicarlo debemos utilizar los tipos definidos en la clase Entity como constantes
  • required = [TRUE|FALSE], donde indicamos si el campos es o no requerido para poder almacenar un registro User en la base de datos.
  • maxlength = [INTEGER], donde indicamos el número máximo de caracteres que permite introducirse en la columna.
Como vemos en el código, solo hemos añadido las propiedades name y datatype pero existen todas las que muestro a continuación y que iremos viendo en posteriores entradas:
Posibles propiedades de una columna
En principio nos vale con las que hemos definido pero para probar alguna más he añadido las propiedades restrictivas  required y maxLengh al campo email quedándome así:

NOTA: Para conocer los posibles tipos que podemos utilizar en DATATYPE podemos escribir Entity. CTRL+SPACE y aparecerán las distinta alternativas:

Tipos para las columnas en la Base de Datos

La segunda clase la llamaremos ApplicationDataContext y debe extender de com.desandroid.framework.ada.ObjectContext. Es el manejador de las clases com.desandroid.framework.ada.Entity de la aplicación y el que realiza las operaciones CRUD que permiten persistir datos en la BD y extraer información de la misma.

Para ver todos sus métodos podemos hacerlo desde el código o bien accediendo a la sección de la página web del framework donde se encuentra toda la documentación de la API de ADA Framework. Veamos nuestro código por orden, de forma descendente:

En primer lugar la declaración de dos constantes donde indicamos qué versión de la base de datos vamos a utilizar y el nombre del fichero que representa esta base de datos DATABASE_VERSION y DATABASE_NAME; sin embargo, esto no es obligatorio, solo lo he declarado para el caso de este ejemplo, ya que como veremos a continuación podemos indicar estos valores de otra forma sin que contengan valores constantes.

A continuación encontramos la declaración de la variable usuariosSet del tipo com.desandroid.framework.ada.ObjectSet cuya función es la de permitir realizar operaciones SELECT, CREATE, UPDATE  y DELETE contra tabla “tUser” de la base de datos.

Observamos que este ObjectSet, en su declaración, tiene definido el tipo de objetos que va a manejar (que deben heredar de com.desandroid.framework.ada.Entity), en nuestro ejemplo User de manera que:

  • Si vamos a realizar alguna de las 3 operaciones de modificación de la base de datos (CREATE, UPDATE, DELETE) nuestro ObjectSet deberá recibir el objeto del tipo indicado entre “<>” con el que se va a trabajar.
  • Si vamos a realizar la operación de extracción de información de la base de datos (SELECT) nuestor ObjectSet se rellenará con objetos de la tabla User.

Finalmente encontramos 3 constructores, de los cuales, al menos 1 es obligatorio (esto nos lo indicará el propio Eclipse). Con los constructores instanciaremos nuestro com.desandroid.framework.ada.ObjectContex indicando, en función del constructor los siguientes parámetros:

  • android.content.Context pContext: Context de Android.
  • java.lang.String pDatabaseName: Nombre del fichero de la Base de datos.
  • int pDatabaseVersion: versión de la base de datos.
Como vemos, si utilizamos alguno de los constructores donde indicamos el nombre y/o versión de al base de datos podemos prescindir de las constantes mencionadas al principio. En principio, y para nuestro ejemplo básico, nos quedaremos con la opción 1 en la que solo pasamos el parámetro Context y añadiremos en el propio constructor la inicialización del com.desandroid.framework.ada.ObjectSet e indicaremos que eleve las posibles excepciones provocadas en dicha inicialización con throws AdaFrameworkException. Queda por tanto así:
Hasta aquí ya tenemos definida nuestra capa de persistencia de nuestro proyecto Android, a continuación solo hay que poner en práctica su funcionamiento. Esto lo vamos a hacer partiendo de una Activity en la que podamos dar de alta Usuarios y a continuación mostrar un listado de los usuarios registrados en la base de datos.
Puesto que esta entrada solo trata sobre explicar ADA Framework nos centraremos en la parte del código que realiza las llamadas a las operaciones de la capa de persistencia.
Nuestro formulario para dar de alta usuarios será el siguiente:
Una vez que clicamos en ENVIAR se ejecutará el código correspondiente al método SAVE del a actividad MainActivity que es el siguiente:
Y con ello obtendremos en la consola de log de Eclipse dedicada a Android un mensaje como el siguiente:
Como vemos, lo que se ha producido es:
  1. Se recogen los valores de los campos del formulario.
  2. Se construye un objeto User con los valores recogidos.
  3. Se invoca al método SAVE del ObjectSet de nuestro ApplicationDataContext pasándole como parámetro el USER.
  4. Se ejecuta la sentencia SQL Insert.
Podemos apreciar la potencia del framework que ha sido capaz de identificar que la tabla tUser no existía en la base de datos y por tanto previamente la ha generado a partir de las anotaciones de la clase User.
Publicado en Android | Etiquetado , , , , | Deja un comentario

ADAFramework ¡¡Qué bueno que viniste!!

Tras la experiencia vivida en mi trabajo con Android me quedé con una espina clavada que hacía que me preguntase ¿Y todo esto tan feo hay que montar para trabajar con la BD en Android? ¿Después de las cosas tan chulas que te permite hacer la capa vista nos encontramos esto? Debe haber algo que lo haga más bonito y ágil…Y lo había:

En base a lo que conocía en cuanto a desarrollo web pregunté a Google si existía algo parecido y tras varias búsquedas simples di con: Android Data Abstraction Framework (@ADAFramework para los twitteros).

Es un Framework de persistencia de datos muy similar a lo que nos proporcionan otros otros Frameworks que había utilizado anteriormente en proyectos de la plataforma J2EE.

¡¡He de reconocerlo!! Lo que más me gustó fue el tema de las anotaciones. Y… ¡¡He de reconocerlo!! Últimamente tengo anotación-manía, no sé si eso es bueno o es malo (tampoco le he preguntado al médico ni él me ha mencionado tomar precauciones al respecto), pero cuando lo encuentro en manuales de referencia entiendo que al menos no es un uso incorrecto de las herramientas ni tampoco una mala práctica (Si alguien piensa que esto no es así, ¡¡Por favor!! que me lo comunique y como se suele decir me lo haré mirar).

Os dejo un par de referencias de cómo utilizarlo y en el próximo post comentaré mi ejercicio práctico para confirmar que funciona perfectamente:

Uso básico de ADAFramework: Cómo crear la base de datos desde tu código Java y como manejar tu entidades para realizar las operaciones CRUD habituales.

Dependencia entre Entidades: Cómo añadir dependencias entre clases desde tu código Java mediante anotaciones y ver esto reflejado en tus tablas de la BD.

Publicado en Android | Etiquetado , , , , , | 1 Comentario

Y por qué ahora un blog…

Hoy por fin me he decidido a comenzar a escribir un blog en el que pueda comentar algunas experiencias de mi vida fuera y dentro del ámbito profesional.

La historia es que hace 2 o 3 años, aprovechando que estaba recibiendo un curso de desarrollo de aplicaciones en Java empecé a escribir directamente en un blog de blogspot pequeños manuales paso a paso de cómo trabajar con los Frameworks de los que iba adquiriendo conociementos, sin embargo, una vez finalizado el curso abandoné esta práctica y hasta hoy no he entendido la verdadera importancia de escribir un blog.

A continuación enumero algun@s motivos/ventajas que se me han ocurrido hoy, ahora mismo, por las que encuentro interesante escribir un blog:

1) Creo que he alcanzado un mínimo de conocimientos para saber si algo que yo puedo contar puede interesar y/o ayudar a otras personas.

2) Me parece un muy buen ejercicio mental y de autodisciplina. El que de vez en cuando organicemos nuestras ideas en la cabeza y las escribamos nos ayudará a aprender a hacer llegar a otras personas lo que queremos expresarles de forma clara y que puedan entenderlo. Además, si lo hacemos con regularidad llegará un momento en que forme parte de nuestra vida cotidiana y se convierta en una tarea igual que la de hacer la comida, sacar al perro, mirar el correo electrónico y tirar la basura (para el que la tire claro ;P).

3) Por el sector en el que trabajo, mi formación está basada en cosas como las que me he propuesto hacer (escribir este blog), es decir, que mis conocimientos no solo provienen de manuales escritos en inglés por las empresas que han creado las herramientas con las que trabajo sino que muchas de las cosas que he aprendido las he leído en otros blogs, páginas webs, foros, “recientemente” redes sociales donde la gente ha decidido compartir su experiencia, y en mi opinión:

No hay nada más valioso que la experiencia que puedan transferirte“.

4) Por que me siento en deuda con La Comunidad. Enlazando con el anterior punto, es Internet el que me ha facilitado mi trabajo y por tanto quiero contribuir con este blog a que eso siga siendo posible para otras personas.

5) Que mejor forma de ver la evolución de uno mismo que leer lo que has ido escribiendo con el paso del tiempo. Esto nos permite no solo saber cómo evolucionamos, sino encaminarnos y dirigirnos a donde creemos que debemos ir. Es una forma de decirse a uno mismo “tengo que mejorar lo que hago cada día” y de incentivarse mentalizándose en que “tenemos que aprender algo nuevo cada día”.

6) No es que me importe más o menos la imagen que quiero dar al mundo sobre mis conocimientos o mi persona, para mi “esto tiene la importancia que tiene, ni más ni menos”, y por eso creo que dentro de su grado de importancia, dar a conocer mis conocimientos puede beneficiarme tanto a mi como a las personas que me rodean. De hecho uno de los motivos que me ha hecho dar un paso adelante en mi decisión por escribir este blog era el efecto que causa a las personas, y en esto me pongo el primero, el leer a alguien que sabe de lo que habla.

Creo que por hoy he dejado claro por qué escribo y con ello quiero invitar a los que aún no se han decidido a que den el “pasito palante” (como decía Bisbal) y nos ilustren y nos guíen.

Publicado en General | Etiquetado | Deja un comentario