Making applications for Android is quite a challenging task. In the process we programmers should write thousands and thousands of lines of code to make sometime even simple tasks. But that’s not all! In the last years, we programmers have struggled with new APIs, and most of them become obsolete in a very short period of time so we have to keep learning those APIs again and again (notable mention: Google Play Services, Facebook SDK or the Android SDK itself).
I would like to present in this article one of the amazing features included in a growing framework that could change the way Android Development is done.
DecleX is a framework that aims to get closer to a fully Declarative Language for Android Development. It is totally based on AndroidAnnotations; it facilitates the writing and the maintenance of apps to the highest level which has not been achieved up to now.
With it, programmers reduce dramatically the time for coding these applications, being able to code 4 to 5 times faster, writing even 90% less code. The maintenance of these applications becomes away much easier, and it opens possibilities to integrate 3rd parties libraries even with 1 single annotation through its Plugin Mechanism.
Views injection has been helping programmers to speed up the development of applications in the last years in Android development. Libraries like ButterKnife and AndroidAnnotations have made possible to get rid of the annoying findViewById method…
But have you ever think that views injections are still a lot of boilerplate code?, if you have a model let’s say a model describing an User, which have the user first name, last name and email.. and you want to display that information in the screen but also permit to the user to modify the information and put that information back to the model, in AndroidAnnotations you would do it like this:
It is a huge improvement, especially compared with the annoying calls to “findViewById”. In raw Android, the amount of lines of code to write these methods would be much longer (and obfuscated).
But, isn’t somehow redundant to have to get the Views from the Activity or Fragment, and then fill these with the model information?, I mean, after all, this is an one-to-one relation between this model and the user interface…
Handling this question I got to the idea of Populating and Recollecting views with DecleX, what if populate a form can be as easy as describing with one word what you need: to show all the data of a model in the user interface. Getting that information back should be very easy as well.
Populating and Recollecting
With DecleX this is easier than ever, what is needed is to declare with a @Populate annotation your field:
The framework will automatically read all the data in the model, and will insert all that data in the user interface… See that @Model will inject the model from wherever is required (Ex. the SQLite database or it’ll be downloaded from a server).
What if you need to make the opposite action?, recollect all the information the user has filled in the interface into a model?…
Or enough with:
Once again, the magic of this framework seems to defy the way we have being doing applications all along the way. And of course, you can combine the logic together
So, in a View where what is required is to display information, for the user to read what is stored, and save the modified information back (very common in the settings of an application for instance), it would be enough with only one Field with a few annotations.
How it works
DecleX reads all the information in the layout, and matches this information with the fields of your model. Let’s use the following model to explain this and other features:
Now, in the Activity or Fragment, the field name is “user”, so DecleX will read the layout declared with @EActivity or @EFragment, and it will match any component in the layout with IDs like “user_firstName”, “user_lastName”… “user_image” with the model User itself, and in this way it will populate and recollect all the information from the interface.
DecleX also automatically link the URL of images, or Resources ID, with an ImageView in the interface. Let’s say that the component with ID: “@+id/user_image” is an ImageView, the framework will load the image in the component automatically for you. To do so, it uses the popular library Picasso from Square, so the image is effectively loaded in Background.
Now, let’s say that we have an interface where we are not only modifying the information about the user, but we also need to display and modify the Address of the user, in our model above, the Address is another object. So we need no extra programming for this, having this Address model:
In our layout, we should reference the address of the user with ids like: “user_address_street”, “user_address_number”, … and that’s it.
A very common task when reading information provided by an user to an app is to validate the user input, so typically we need to have the reference to all the components in the interface, to be able to validate them, DecleX came also with a solution that keeps the validation as simple as any other feature in the framework, for this, it uses the popular library Saripaar
When reading the information from the user interface, the validations would be run, and if it fail the process would stop, and a message would be shown to the user (with Saripaar you can write the message that you want to display, most validations have some configuration, and you can also create your own validations).
It is also common the situation where it is needed to process the information before displaying it in the user interface or when recollecting the information the user provided. For instance, let’s say that we should display the user full name in a field, but in our model, we are able to store only the first and last name. DecleX can read not only the fields of a Modal, but also methods. In our provided User model, there are a method named “fullName” which returns a String (this is used by the @Populate annotation). So, we can in the user interface to have a TextView with the id “@+id/user_fullName”, where the full name of the user will be displayed.
AdapterViews and RecyclerView
Once that we get into the realm of the lists, to inject all the data, and display all the data in the user interface becomes a really complicated task. Even with the use of some good tools, we cannot get rid of concepts like ListAdapters and RecyclerView Adapters and Holder. Of course, if we need to have a complete full control of every item of our ListView, GridView, Spinner, RecyclerView… or any of the other views that fulfill the categories in question, it is understandable to use these Adapters, but most of the time, the only thing that we need is to get a list of elements displayed directly in the screen…
Well, let’s say that we have in a SQLite Database a list of users, what we need is to display that list of users in the interface. Let’s see how to do the task of loading all the users from the Database, and populate a ListView with the those users information:
And in the layout we have:
And voilà, since this model is stored in the SQLite database, it would be completely loaded with the @Model annotation, @Populate will search in the xml layout file an AdapterView or RecycleView with the id “@+id/users”, from there it will look for the “tool:listitem” (the item that will be used to show the information of the user in the list view). With all this information a ListAdapter will be built, a HolderView is also created to use the View Holder pattern, keeping the method efficient. And you can even make a query to filter the users that you need to show:
The layout referenced by “@layout/item_user” should have the views id with the same name than the fields in the class User, ex. “@+id/firstName”, “@+id/image”
So with DecleX you have completely covered the lists. If it is needed to personalize the adapter, it exists another annotation @AdapterClass, which receives a subclass of ListAdapter and permits to have full control over the generated Adapter, still keeping the amount of information that we should provide minimum.
Actions are a very powerful component of DecleX. Populating and recollecting are completely integrated with the actions mechanism in the framework. Exist two main actions to be used in the action methods, they are: $Populate(), and $Recollect()… but this mechanism is embedded into the $PutModel and $LoadModel actions.
Let’s see an example, let’s say that our application has a wizard with two fragments, named “UserFragment” and “AddressFragment”, they are used to collect all the information about an user, firstly the basic user information (name, email, etc..), then the user address information, and after this all the data is sent to the back-end and saved in the database. So, in this process, we should not save the user to the database in the first fragment, only in the second one…. Let’s see the code:
And the fragment to recollect the address and send the user to back-end:
So, in this example, we use $Recollect() in the first fragment, because it is not our intention to save the user yet (send it to the back-end for instance), until the second fragment has been submitted. Then a confirmation is prompt to the user. We see how the powerful Actions mechanism permits to get rid completely of the very verbose listeners in Java, note that the code from “$PutModel()” will be executed only if “Yes” is pressed as well as the Failed or final “Toast” would be run once that the model “user” be sended to the backend (or if the upload fails).
$PutModel, before sending the model to the server and saving it into SQLite, it will effectuate a normal recollect, which will run the validations over the information provided by the user, and if any error is found, the corresponding validating messages will be displayed, so the model will be not sent until the validations has been successfully passed. If the model is uploaded, a toast is shown with information about the user (see also how Formatted Syntax is used in the toast, to create easily the string to be shown).
For a fully understanding of Action Syntax in DecleX I recommend to check the article:
Action Syntax in DecleX, an elegant code, easier to read and write.
Action Syntax in DecleX helps to write easier applications with Java, and it reduces the maintenance time to a breeze.
There’s a full Expenses Manager application provided as an example of the use of the framework, all the following DecleX features are used:
- Populating and Recollecting.
- Validation of data when Recollecting from the User Interface.
- Connecting to a back-end server using OAuth 2.0.
- Using Actions in the methods.
- Using @LocalDBModel to operate over the Local DB (SQLite, ActiveAndroid ORM)
The application it is basically an expenses manager, where after registered, the user can Create Expenses, Edit and Remove them. Also the expenses can be filtered through different queries to the DataBase. All the data is synchronized with the back-end Server, and the user it is able to Edit his profile.
Download it here:
declex-example-expenses — DecleX Example App: Expenses manager
Let’s try it!
Populating and recollecting data into/from views in DecleX is a powerful tool built in the core of the framework itself, it makes honor to the claim of the framework to be able to reduce up to 90% the amount of raw Android code that a programmer has to write to build an application.
So, now the reader knows more about a really game changing tool for Android Development. With it we can make applications faster, get rid of all that boilerplate code and even of the verbosity of Java language, we can be more focused in what is important in our programs. We make applications faster and with better quality, and the maintenance of them becomes an easier task.
DecleX has the power to be integrated in all the fields of Android Development nowadays. The simplicity of its API make it ideal for fast learning Android Development. On it’s way it can become the guide to follow to program the applications since now on.
I will keep posting features about the framework, since the possibilities to make better applications with it seems to be infinite!.
Let me know what you think about it in your comments, and your experiences with the framework when you try it (so, go to the GitHub Project and try it right now!)… Feel free to contribute to the development of it ;).