Simplifica el desarrollo de aplicaciones de Android con Anko
Spanish (Español) translation by Naudys Angulo (you can also view the original English article)
Diseñado por JetBrains, la organización detrás de Kotlin, Anko es una biblioteca de código abierto que puede cambiar radicalmente la forma en la cual creas aplicaciones de Android. Aprovecha la sintaxis de Kotlin para ofrecer una gran colección de funciones auxiliares que te ayudan a reducir la verbosidad de tu código al mismo tiempo que mejoran su rendimiento.
Anko también funciona como DSL, abreviatura de lenguaje específico de dominio, para crear diseños de Android. En otras palabras, este puede actuar como una alternativa segura, dinámica y más reutilizable a los archivos XML de diseño, que, como ya sabrás, tienden a ser difíciles de manejar para aplicaciones grandes.
En este tutorial, te ayudaré a comenzar con Anko mostrándote cómo usar algunas de sus funciones más populares.
1. Configuración del proyecto
Para poder utilizar las funciones principales de Anko en tu proyecto de Android Studio, todo lo que necesitas hacer es agregar la siguiente dependencia de implementación en el archivo build.gradle del módulo de la aplicación:
1 |
implementation 'org.jetbrains.anko:anko:0.10.1' |
Sin embargo, si deseas que Anko trabaje con widgets de las bibliotecas de soporte de Android, necesitarás las siguientes dependencias adicionales:
1 |
implementation 'org.jetbrains.anko:anko-appcompat-v7:0.10.1' |
2 |
implementation 'org.jetbrains.anko:anko-design:0.10.1' |
3 |
implementation 'org.jetbrains.anko:anko-recyclerview-v7:0.10.1' |
4 |
implementation 'org.jetbrains.anko:anko-cardview-v7:0.10.1' |
2. Crear diseños
El Anko DSL tiene funciones de ayuda para casi todos los widgets que ofrecen el SDK de Android y las bibliotecas de soporte de Android. Utilizándolos, puedes crear tus diseños mediante programación. Los nombres de las funciones coinciden con los nombres de los widgets, pero comienzan con una letra minúscula. Por ejemplo, para crear un widget TextView, usa la función textView() de Anko. De manera similar, para crear un widget FloatingActionButton, puedes usar la función floatingActionButton().
Dentro de las funciones, tendrás acceso a todas las propiedades y detectores de eventos de los widgets asociados. Por ejemplo, puedes cambiar el tamaño del texto de un widget TextView actualizando el valor de la propiedad textSize dentro de la función textView (). De manera similar, puedes agregarle un detector de eventos al hacer clic utilizando el método onClick.
Para ayudarte a comprender mejor cómo usar el DSL, aquí hay un diseño de muestra para una aplicación de navegador, que contiene un widget EditText y un widget WebView colocado dentro de un widget LinearLayout cuya orientación es VERTICAL:
1 |
linearLayout { |
2 |
orientation = LinearLayout.VERTICAL |
3 |
|
4 |
var myWebView:WebView? = null |
5 |
|
6 |
editText { |
7 |
inputType = InputType.TYPE_TEXT_VARIATION_URI |
8 |
imeOptions = EditorInfo.IME_ACTION_GO |
9 |
onEditorAction { _, _, _ -> |
10 |
myWebView?.loadUrl(text.toString()) |
11 |
}
|
12 |
}
|
13 |
|
14 |
myWebView = webView { |
15 |
webViewClient = WebViewClient() |
16 |
}
|
17 |
}
|
El código escrito en el DSL de Anko es muy legible e intuitivo, pero cuesta acostumbrarse a él, especialmente si ya eres un desarrollador experimentado de Android. Ya no tienes que asignar identificadores a tus widgets, o usar el método findViewById() para referenciarlos, porque a diferencia de los diseños basados en XML, los diseños basados en DSL de Anko pueden encapsular la lógica de negocio de tu aplicación. Por ejemplo, puedes ver que el widget EditText definido arriba tiene un escuchador de eventos OnEditorAction que llama directamente al método loadUrl()del widget WebView para cargar la URL que el usuario escribió.
Además, ya no tienes que llamar al método setContentView() porque Anko lo llama automáticamente dentro del método onCreate() de tu clase Activity.
El DSL incluye varios atajos que puedes utilizar para hacer tus diseños más concisos. Por ejemplo, puedes pasar directamente cadenas a sus funciones para asignar etiquetas a los widgets. A menudo, también puedes evitar establecer explícitamente los parámetros de diseño, como la anchura y la altura, porque los maneja automáticamente. El siguiente código de ejemplo muestra cómo crear un diseño que contenga dos widgets TextView de forma muy concisa:
1 |
verticalLayout { |
2 |
textView("One") |
3 |
textView("Two") |
4 |
}
|
A modo de comparación, este es el aspecto que tendría el diseño anterior si se creara de forma convencional:
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<LinearLayout
|
3 |
xmlns:android="https://schemas.android.com/apk/res/android" |
4 |
android:layout_width="match_parent" |
5 |
android:layout_height="match_parent" |
6 |
android:orientation="vertical"> |
7 |
<TextView
|
8 |
android:layout_width="wrap_content" |
9 |
android:layout_height="wrap_content" |
10 |
android:text="One"/> |
11 |
<TextView
|
12 |
android:layout_width="wrap_content" |
13 |
android:layout_height="wrap_content" |
14 |
android:text="Two"/> |
15 |
</LinearLayout>
|
Por último, vale la pena mencionar que los diseños creados con el DSL de Anko tienden a cargar más rápido que los diseños regulares porque no se requiere el análisis de XML.
3. Creación de diálogos
Si crees que usar la clase AlertDialog.Builder para crear diálogos es mucho trabajo, definitivamente no estás solo. Por ejemplo, así es como se crea normalmente un diálogo simple que muestra un título, un mensaje y un botón "OK":
1 |
AlertDialog.Builder(this@MyActivity) |
2 |
.setTitle("My Dialog") |
3 |
.setMessage("This is a test message") |
4 |
.setPositiveButton("OK", null) |
5 |
.create() |
6 |
.show() |
Con Anko, sin embargo, la creación del diálogo anterior simplemente implica una llamada a la función alert(), que acepta el título y el mensaje del diálogo como argumentos.
1 |
alert("This is a test message", "My Dialog") { |
2 |
yesButton { } |
3 |
}.show() |
Ten en cuenta que no tienes que pasar un contexto a la función alert(). Esta infiere el contexto automáticamente.
Anko tiene funciones similares con nombres intuitivos para ayudarte a crear rápidamente toasts y snackbars. El siguiente código muestra cómo crear toasts de corta y larga duración:
1 |
toast("This is a short toast") |
2 |
longToast("And this is a long toast") |
4. Creando Intents
Siempre que necesitas iniciar una nueva actividad en tu aplicación, debes crear una intent. Además, si quieres enviar datos a la actividad, debes incluirlos en la intent como uno o más extras.
Con la función startActivity() de Anko, normalmente puedes realizar ambas tareas en una sola línea de código. Por ejemplo, el siguiente código muestra cómo lanzar una actividad llamada MiActividad y pasarle dos extras, un extra de cadena llamado "PERSONA" y un extra de número entero llamado "EDAD":
1 |
startActivity<MyActivity>("PERSON" to "Bob", "AGE" to 25) |
Anko también tiene funciones de ayuda para varias tareas comunes basadas en intent. Por ejemplo, puedes utilizar su función browse() para abrir una URL en la aplicación del navegador por defecto del dispositivo. Del mismo modo, puedes utilizar la función email() para abrir la aplicación de correo electrónico por defecto y redactar un correo electrónico.
1 |
// Open browser
|
2 |
browse("https://tutsplus.com") |
3 |
|
4 |
// Open default E-mail app
|
5 |
email("bob@example.com", "Hello", "This is a test email") |
5. Uso de la base de datos SQLite
Aunque todas las aplicaciones Android pueden crear y utilizar bases de datos SQLite sin dependencias adicionales, muchos desarrolladores eligen bases de datos de terceros como Realm. ¿Por qué? Bueno, tal vez porque la API SQLite de Android es extremadamente verbosa, de bajo nivel, y requiere una buena comprensión de SQL. Afortunadamente, Anko tiene funciones de ayuda de SQLite para resolver todos esos problemas.
Digamos que tenemos una simple base de datos SQLite creada con el siguiente código:
1 |
val myDB = openOrCreateDatabase("test.db", |
2 |
Context.MODE_PRIVATE, null) |
Con Anko, ahora puedes añadir una tabla a la base de datos anterior simplemente utilizando la función createTable(), que espera el nombre de una o más tablas juntas o tuplas especificando los nombres y tipos de datos de sus columnas. El siguiente código de ejemplo crea una tabla llamada PERSONA que tiene cuatro columnas, una de las cuales sirve como clave primaria:
1 |
myDB.createTable("PERSON", true, |
2 |
"NAME" to TEXT, |
3 |
"AGE" to INTEGER, |
4 |
"NET_WORTH" to REAL, |
5 |
"ID" to INTEGER + PRIMARY_KEY) |
Además, para insertar filas en la tabla, ya no tienes que depender de la clase ContentValues(). Puedes llamar directamente a la función insert() en la base de datos, especificar el nombre de la tabla a la que quieres añadir la fila, y luego pasarle los valores de las columnas en forma de tuplas.
1 |
// Add a row
|
2 |
myDB.insert("PERSON", |
3 |
"NAME" to "Bob Martin", |
4 |
"AGE" to 25, |
5 |
"NET_WORTH" to 2500.50, |
6 |
"ID" to 100) |
7 |
|
8 |
// Add another row
|
9 |
myDB.insert("PERSON", |
10 |
"NAME" to "Jane Flores", |
11 |
"AGE" to 32, |
12 |
"NET_WORTH" to 21500.80, |
13 |
"ID" to 101) |
Por último, para consultar la base de datos, puedes utilizar la función select(), seguida opcionalmente de una cadena de funciones de nombre intuitivo como whereSimple(), orderBy() y groupBy(). Por ejemplo, para hacer una lista de los nombres y las edades de todas las personas de la tabla anterior cuyo patrimonio neto es superior a 10000, puedes utilizar el siguiente código:
1 |
myDB.select("PERSON", "NAME", "AGE") |
2 |
.whereSimple("NET_WORTH > ?", "10000.0").exec { |
3 |
// More code here
|
4 |
}
|
El resultado de la consulta anterior será, como es de esperar, un objeto Cursor. Convertirlo en una Lista que contenga los valores reales de las columnas de todas las filas es algo más complicado porque implica crear un objeto que implemente la interfaz RowParser y pasarlo a la función parseList().
La interfaz RowParser solo tiene un método, el método parseRow(), dentro del cual tendrás acceso a los valores de las columnas de una fila. La forma de utilizar los valores depende, por supuesto, de ti. Por ahora, vamos a concatenarlos e imprimirlos. El siguiente código te muestra cómo hacerlo:
1 |
parseList(object: RowParser<String>{ |
2 |
override fun parseRow(columns: Array<Any?>): String { |
3 |
// Concatenate the values of the first and second columns,
|
4 |
// which happen to be NAME and AGE
|
5 |
return "${columns[0]} (${columns[1]} years old)" |
6 |
}
|
7 |
}).forEach { |
8 |
println(it) // print the concatenated values |
9 |
}
|
10 |
|
11 |
// Result is:
|
12 |
// Jane Flores (32 years old)
|
Ten en cuenta que no siempre tienes que crear un objeto RowParser manualmente. Si los resultados de tu consulta contienen solo una columna, puedes utilizar uno de los muchos analizadores integrados de Anko.
Los nombres de los analizadores integrados se basan en los tipos de datos de las columnas. Por ejemplo, si el tipo de datos es TEXTO, puedes utilizar un StringParser. O si el tipo de datos es INTEGER, puede utilizar un IntParser. El siguiente código muestra cómo utilizar un StringParser para listar simplemente los nombres de todas las personas de nuestra base de datos:
1 |
myDB.select("PERSON", "NAME").exec { |
2 |
parseList(StringParser).forEach { |
3 |
println(it) |
4 |
}
|
5 |
}
|
6 |
|
7 |
// Result is:
|
8 |
// Bob Martin
|
9 |
// Jane Flores
|
Conclusión
En este tutorial, has aprendido a utilizar el DSL de Anko y las funciones de ayuda para simplificar el desarrollo de aplicaciones Android. También has visto cómo Anko simplifica las operaciones relacionadas con SQLite. Espero que ahora te des cuenta de lo bien pensada y útil que está la librería.
En mi opinión, si ya eres competente en Kotlin, no hay realmente ninguna razón por la que no debas usar Anko para mejorar aún más tu eficiencia y experiencia de desarrollo. Para saber más sobre ella, consulta su wiki oficial.
Y ya que estás aquí, echa un vistazo a algunos de nuestros otros posts sobre Kotlin y el desarrollo de aplicaciones Android.


SDK de AndroidJava vs. Kotlin: ¿Deberías usar Kotlin para el desarrollo de Android?Jessica Thornsby

SDK de AndroidIntroducción a los componentes de la arquitectura de AndroidTin Megali

SDK de AndroidCómo empezar con RxJava 2 para AndroidJessica Thornsby

KotlinKotlin desde cero: Más diversión con las funcionesChike Mgbemena



