Desarrollo moderno de Android con Kotlin, Parte 1

Es realmente difícil encontrar un proyecto que cubra todas las novedades en Android Development, así que decidí escribir uno. En este artículo utilizaremos lo siguiente:

https://twitter.com/brijeshmasrani/status/901291501870751745

0. Android Studio 3, beta 1 
1. Lenguaje de Kotlin 
2. Variantes de compilación 
3. Restricción de restricciones 
4. Biblioteca de enlace de datos
5. Arquitectura MVVM + patrón de repositorio (con mapeadores) + Contenedores de Android Manager ( Parte 2
6. Rx Java2 y cómo nos ayuda en la arquitectura ( Parte 3
7. Daga 2.11, qué es Inyección de Dependencia, por qué debería usarla. ( Parte 4
8. Retrofit (con Rx Java2) 
9. Habitación (con Rx Java2)

¿Cuál será nuestra aplicación? 
Nuestra aplicación será la más simple que cubra todas las cosas mencionadas: tendrá solo una característica que recuperará todos los repositorios de GitHub de las muestras de usuarios , guardará esos datos en la base de datos local y los mostrará a los usuarios.

Trataré de explicar tantas líneas de código como pueda. Puedes seguir buscando en commits de código que publiqué en github.

Vamos a ensuciarnos las manos:

0. Android studio

Para instalar Android Studio 3 beta 1, debe ir a esta página .

Nota: Si desea instalarlo junto con alguna versión anterior, en Mac debe cambiar el nombre de la versión anterior en la carpeta de la aplicación, por ejemplo, “Android Studio Old”. Puede encontrar más información, incluyendo Windows y Linux aquí .

Android Studio tiene soporte para Kotlin. Ve a Crear proyecto de Android . Verá algo nuevo allí: la casilla de verificación con etiqueta incluye el soporte de Kotlin . Está marcado por defecto. Presiona siguiente dos veces y selecciona Empty Activity, luego termina . 
Felicidades! Has hecho la primera aplicación de Android en Kotlin :)

1. Kotlin

Puedes ver MainActivity.kt:

La extensión .kt significa que el archivo es Kotlin .

MainActivity: AppCompatActivity () significa que estamos ampliando AppCompatActivity.

Además, todos los métodos deben tener una palabra divertida y en Kotlin no es necesario usar ; pero puedes si quieres. Tienes que usar la palabra anular y no una anotación.

Entonces, ¿cuál es el significado de ? en savedInstanceState: Bundle? ? Significa que el parámetro savedInstanceState puede ser del tipo Bundle o null . Kotlin es un lenguaje de seguridad nulo. Si usted tiene:

var a: String

obtendrá un error de compilación, causa una debe ser inicializado y no puede ser nulo . Eso significa que tienes que escribir:

var a: String = "Valor inicial"

Además, obtendrá un error de compilación si lo hace:

a = nulo

Para hacer una nullable, debes escribir:

var a: ¿Cadena?

¿Por qué es esta característica importante del lenguaje de Kotlin? Nos ayuda a evitar NPE . Los desarrolladores de Android están tan cansados ​​de NPE. Incluso el creador de null, señor Tony Hoare, se disculpó por haberlo inventado . Digamos que tenemos NULL nombreTextView . El siguiente código nos dará NPE si es nulo:

nameTextView.setEnabled (true)

Pero Kotlin, en realidad, es bueno y no nos permitirá ni siquiera hacer tal cosa. Nos obligará a usar? o !! operador. Si usamos ? operador:

nameTextView? .setEnabled (true)

la línea se continuará solo si nameTextView no es un nulo. En otro caso, si usamos !! operador:

nameTextView !!. setEnabled (true)

nos dará NPE si nameTextView es nulo. Es solo para aventureros :).

Esta fue una pequeña introducción para Kotlin. A medida que avanzamos, me detendré para describir otro código específico de Kotlin.

2. Desarrollar variantes

A menudo en desarrollo, tienes diferentes entornos. Los más habituales son los entornos de prueba y producción . Esos entornos pueden diferir en url del servidor, icono, nombre, API de destino, etc. Por lo general, en cada proyecto al inicio tengo lo siguiente:

  • FinalProduction , que va a Google Play Store
  • demoProduction , que es una versión con url del servidor de producción con nuevas características que todavía no están en Google Play Store. Nuestros clientes pueden tener esta versión instalada junto a la de Google Play para que puedan probarla y darnos su opinión.
  • demoTesting, igual que demoProduction con prueba server url
  • falsa, útil para mí como desarrollador y para diseñadores. A veces tenemos el diseño listo y nuestra API aún no está lista. Esperar a que la API esté lista para comenzar el desarrollo no es una solución. Esta variante de compilación se proporciona con datos falsos, por lo que el equipo de diseño puede probarla y darnos su opinión. Es realmente útil no posponer las cosas. Una vez que la API esté lista, estamos moviendo nuestro desarrollo al entorno demoTesting .

En esta aplicación, los tendremos todos. Diferirán en applicationId y name. Hay un nuevo api in gradle 3.0.0 flavorDimension que le permite mezclar diferentes sabores de productos, para que pueda mezclar sabores demo y minApi23 . En nuestra aplicación, usaremos simplemente “default” flavorDimension. Vaya a build.gradle para la aplicación e inserte este código dentro de android {}

Vaya a strings.xml y elimine la cadena de app_name, para que no tengamos conflictos. A continuación, presione Sincronizar ahora. Si va a construir variantes que están a la izquierda de la pantalla, puede ver 4 variantes de compilación diferentes donde cada una de ellas tiene dos tipos de compilación: depuración y liberación. Cambie a la variante de compilación demoProduction y ejecútelo. Luego cambie a otro y ejecútelo. Debería ver dos aplicaciones con diferentes nombres.

3. Restricción

Si abre la clase activity_main.xml, debería ver que el diseño es ConstrainLayout. Si alguna vez codifica la aplicación iOS, conoce AutoLayout. ConstraintLayout es realmente similar a esto. Incluso están usando el mismo algoritmo Cassowary .

Las restricciones nos ayudan a describir cuáles son las relaciones de puntos de vista. Para cada vista debe tener 4 restricciones, una para cada lado. En este caso, nuestra vista está restringida a primaria para cada lado.

Si mueve la vista de texto Hello World un poco hacia arriba en la pestaña Diseño, en la pestaña Texto aparecerá una nueva línea:

aplicación: layout_constraintVertical_bias = "0.28"

La pestaña Diseño y la pestaña Texto están sincronizadas. Nuestro movimiento en la pestaña Diseño afecta a xml en la pestaña Texto y viceversa. El sesgo vertical describe la tendencia vertical de la vista a sus restricciones. Si desea que la vista se centre verticalmente, debe usar:

aplicación: layout_constraintVertical_bias = "0.28"

Hagamos que nuestra actividad muestre solo un repositorio. Tendrá nombre de repositorio, número de estrellas, propietario y mostrará si el repositorio tiene problemas o no.

Para obtener un diseño como este, xml tiene que verse así:

No se confunda con herramientas: texto . Simplemente nos ayuda a tener una buena vista previa del diseño.

Podemos notar que nuestro diseño es plano. No hay diseños anidados. Debería usar diseños anidados, ya que, en la medida en que lo haga, puede afectar el rendimiento. Más información al respecto que puedes encontrar aquí . Además, ConstraintLayout funciona con diferentes tamaños de pantalla realmente buenos:

y tengo la sensación de que puedo lograr el resultado deseado realmente rápido. 
Esa fue una pequeña introducción en ConstraintLayout. Puede encontrar el laboratorio de códigos de Google aquí y hay una documentación sobre CL en github .

4. Biblioteca de enlace de datos

Cuando escuché sobre la biblioteca de enlace de datos, lo primero que me pregunté fue: “Butterknife funciona realmente bien para mí”. Además, estoy usando un complemento que me ayuda a obtener vistas desde xml. ¿Por qué debería cambiarlo? “. Una vez que aprendí más sobre el enlace de datos tuve la misma sensación que tuve cuando usé ButterKnife por primera vez.

¿Qué ButterKnife nos ayuda?

ButterKnife nos ayuda a deshacernos del aburrido findViewById. Entonces, si tienes 5 vistas, sin Butterknife tienes 5 + 5 líneas para unir tus puntos de vista. Con ButterKnife tienes 5 líneas. Y eso es.

¿Para qué sirve ButterKnife?

ButterKnife aún no resuelve el problema de mantenimiento de código. Cuando utilicé ButterKnife, a menudo me encontraba obteniendo una excepción de tiempo de ejecución, porque borraba la vista en xml y no borraba el código de enlace en la clase de actividad / fragmento. Además, si desea agregar vista en xml, debe volver a hacer el enlace. Es realmente aburrido Estás perdiendo tu tiempo para mantener las ataduras.

¿Qué pasa con la biblioteca de enlace de datos?

¡Hay muchos beneficios! ¡Con la biblioteca de enlace de datos puede vincular sus vistas con solo una línea de código! Dejame mostrarte como funciona. Agreguemos la biblioteca de enlace de datos a nuestro proyecto:

// at the top of file 
apply plugin: 'kotlin-kapt'

android {
//other things that we already used
dataBinding.enabled = true
}
dependencies {
//other dependencies that we used
kapt "com.android.databinding:compiler:3.0.0
-beta1"
}

Tenga en cuenta que la versión del compilador de enlace de datos es la misma que la versión gradle en su archivo build.gradle del proyecto :

classpath 'com.android.tools.build:gradle:3.0.0-beta1'

Presione Sincronizar ahora . Vaya a la clase activity_main.xml y ajuste el diseño de restricciones con la etiqueta de diseño :

Tenga en cuenta que debe mover todos los xmlns a la etiqueta de diseño. A continuación, presione el icono de compilación o use el atajo Cmd + F9 . Necesitamos crear un proyecto para que la biblioteca de enlace de datos pueda generar la clase ActivityMainBinding que usaremos en nuestra clase MainActivity.

Si no hace Build del proyecto, no verá la clase ActivityMainBinding porque se genera en tiempo de compilación. Todavía no terminamos de enlazar, solo dijimos que tenemos una variable no nula que es el tipo ActivityMainBinding. Además, como se puede notar que no puse ? al final de ActivityMainBinding y no lo inicialicé. ¿Como es posible? El modificador lateinit nos permite tener variables no nulas esperando la inicialización. Al igual que en ButterKnife, la inicialización de enlace debe hacerse en el método onCreate, una vez que nuestro diseño esté listo. Además, no debe declarar el enlace en el método Crear, porque probablemente lo use fuera del alcance del método Crear. Nuestrael enlace no debe ser nulo, por eso usamos lateinit . Al usar el modificador tardinit no tenemos que anular la verificación de lavariable de enlace cada vez que accedemos a ella.

Inicialicemos nuestra variable de enlace. Debes reemplazar:

setContentView (R.layout.activity_main)

con:

binding = DataBindingUtil.setContentView (this, R.layout. activity_main )

¡Eso es! Usted vincula exitosamente sus puntos de vista. Ahora puede acceder y aplicar algunos cambios. Por ejemplo, cambiemos el nombre del repositorio a “Artículo mediano de Android moderno”:

binding.repositoryName. text = "Artículo mediano de Android moderno"

Como puede ver, podemos acceder a todas las vistas (las que tienen una identificación , por supuesto) desde activity_main.xml a través de la variable de enlace . Es por eso que Data Binding es mejor que ButterKnife .

Getters y setters en Kotlin

Probablemente ya hayas notado que no tenemos el método .setText () como hacemos en Java. Me gustaría detenerme aquí para explicar cómo los getters y setters trabajan en Kotlin comparando con Java.

Primero, debes saber por qué estamos usando setters y getters. Lo estamos usando para ocultar variables de la clase y para permitir el acceso solo a través de métodos, de modo que podamos ocultar los detalles de la clase de los clientes de la clase y prohibir a los mismos clientes cambiar nuestra clase directamente. Digamos que tenemos la clase Square en Java:

Utilizando el método de seta () estamos prohibiendo clientes de la clase para establecer un valor negativo a un lado causa de la plaza no debe ser negativo. Usando este enfoque tenemos que hacer una privacidad, por lo que no se puede establecer directamente. Eso también significa que el cliente de nuestra clase no puede obtener el a directamente, así que tenemos que proporcionar un getter. Ese getter devuelve a . Si tiene 10 variables con requisitos similares, debe proporcionar 10 captadores. Escribir tales líneas es lo aburrido donde usualmente no usamos nuestra mente.

Kotling hace que la vida de nuestro desarrollador sea más fácil. Si estás llamando

var side: Int = square.a

eso no quiere decir que usted está accediendo a una forma directa. Es lo mismo que:

int side = square.getA ();

en Java causa Kotlin autogenera getters y setters predeterminados. En Kotlin, solo si tiene un setter o getter especial, debe especificarlo. De lo contrario, Kotlin lo genera automáticamente para usted:

var a = 1 
set (valor) { field = Math.abs (value)}

campo ? ¿Qué es esto ahora? Para dejarlo en claro, veamos este código:

var a = 1 
set (valor) {a = Math.abs (value)}

Esto significa que está llamando al método set dentro del método set porque no hay acceso directo a la propiedad en Kotlin World. Esto hará una recursión infinita. Cuando llama a = algo , automáticamente llama al método de configuración . 
Espero que ahora esté claro por qué debe usar la palabra clave de campo y cómo funcionan los iniciadores y los buscadores.

Regresemos a nuestro código. Me gustaría presentarle una característica más de Kotlin, aplique :

aplicar le permite llamar a múltiples métodos en una instancia.

Todavía no terminamos con Enlace de datos, hay más cosas geniales. Hagamos una clase de modelo de Ui para Repositorio (Esta es la clase de Modelo de IU para el Repositorio de Github, contiene datos que se deben mostrar, no se extravíe con el Patrón de Repositorio). Para hacer una clase de Kotlin debes ir a Nuevo -> Archivo / Clase de Kotlin:

Repositorio de clase (var repositoryName: String?, var repositoryOwner: String?, var numberOfStars: Int?, var hasIssues: Boolean = false)

En Kotlin, el constructor primario es parte de un encabezado de clase. Si no quiere proporcionar el segundo constructor, ¡eso es todo! Tu trabajo de clase finaliza aquí. No hay parámetros de constructor para los campos que se asignan, no hay getters y setters. Toda la clase en una sola línea!

Vuelve a la clase MainActivity.kt y crea una instancia de la clase Repository:

var repository = Repository ("Artículo de repositorio de Android mediano", 
"Mladen Rakonjac", 1000, cierto)

Como puede observar, no hay una nueva palabra clave para la construcción de objetos.

Ahora vayamos a activity_main.xml y agreguemos la etiqueta de datos :

<data> 
<variable
name = "repository"
type = "me.mladenrakonjac.modernandroidapp.uimodels.Repository"
/>
</ data>

Podemos acceder a esta variable de repositorio que es tipo de repositorio en nuestro diseño. Por ejemplo, podemos hacer lo siguiente en TextView con el ID de repository id:

android: text = "@ {repository.repositoryName}"

La vista de texto del nombre del repositorio mostrará el texto que se obtiene de la propiedad repositoryName de la variable del repositorio . Lo único que queda es vincular la variable de repositorio de xml a repositorio desde MainActivity.kt. 
Presione Build para hacer que la biblioteca de enlace de datos genere las clases necesarias y regrese a la actividad principal y agregue estas dos líneas:

Unión. repository = repository 
binding.executePendingBindings ()

Si ejecuta la aplicación, verá que la vista de texto mostrará “Artículo de repositorio de Android mediano”. Buena característica, ¿eh? :)

Pero, ¿y si hacemos lo siguiente?

Handler (). PostDelayed ( { repository.repositoryName = "Nuevo nombre" } , 2000)

¿Se mostrará el nuevo texto después de 2000 millis? No, no lo hará. Tienes que configurar el repositorio de nuevo. Algo como esto funcionará:

Handler (). PostDelayed ( { repository.repositoryName = 
enlace de "nombre nuevo" . Repository = repositorio
binding.executePendingBindings () } , 2000)

Pero, será aburrido si tenemos que hacer esto cada vez que cambiemos alguna propiedad. Hay una mejor solución llamada Property Observer.
Primero describamos cuál es el patrón de Observer porque también lo necesitaremos en la sección rxJava:

Probablemente, ya ha escuchado para http://androidweekly.net/ . Es un boletín semanal sobre Android Development. Si desea recibirlo, debe suscribirse y proporcionar su dirección de correo electrónico. Después de un tiempo, si lo decide, puede dejar de ir a la opción de cancelar suscripción en su sitio.

Este es un ejemplo de patrón Observer / Observable. En este caso, Android Weekly es observable , emite boletines de noticias cada semana. Los lectores son observadores porque se suscriben, esperan nuevas emi- siones y una vez cuando lo reciben, lo leen y si algunos de ellos deciden que no le gusta, puede dejar de escucharlo.

Property Observer en nuestro caso es el diseño xml, que escuchará los cambios en la instancia del Repositorio. Entonces, el repositorio es observable. Por ejemplo, una vez que se cambia la propiedad del nombre del repositorio en la instancia de la clase Repository, xml debe actualizarse sin llamar:

Unión. repository = repository 
binding.executePendingBindings ()

¿Cómo hacerlo utilizando la biblioteca de enlace de datos? La biblioteca de enlace de datos nos proporciona la clase BaseObservable que debe implementar la clase Repository:

BR es una clase que se genera automáticamente una vez cuando se utiliza laanotación Bindable . Como puede ver, una vez que se establece el nuevo valor lo notificamos. Ahora puede ejecutar la aplicación y verá que el nombre del repositorio cambiará después de 2 segundos sin llamar a executePendingBindings () nuevamente.

Eso fue todo por esta parte. En la siguiente parte, escribiré sobre el patrón MVVM y el patrón Repository y escribiré sobre los administradores de Wrapper de Android. Puedes encontrar todo el código aquí . Este artículo cubre el código hasta la siguiente confirmación .

Puedes encontrar la Parte 2 aquí:

Gracias por leer y sígueme para más artículos como este. :)

Para conocer mas tecnologias pueden seguirme en mis redes sociales:

facebook: https://web.facebook.com/wilbeDEV/

facebook: https://web.facebook.com/TechManiako/

Grupo_facebook: https://web.facebook.com/groups/166091130742535/

YouTube: https://www.youtube.com/c/WILBERCCORIDEVELOPER

Blogs: https://www.techmaniako.com/ED/

GitHub: https://github.com/wilberCcoriHuman

web_oficial : https://www.techmaniako.com