>

Kotlin: “Pasito a pasito” con MVP #AndroidMeetsKotlin

Francisco Manuel López Jurado     Colaboraciones    19/01/2018


En el post anterior explicamos qué es MVP, cómo aplicarlo y las clases bases que necesitamos para tener una buena base donde se asentará todos los nuevos desarrollo para los distintos módulos de nuestra app . En esta ocasión, haciendo uso de los componentes bases (BasePresenter, definición de contratos, etc) crearemos nuestro primer bloque funcional. Se trata de todo lo necesario para inyectar/configurar nuestra MainActivity, la cuál hará una llamada a servicio y posteriormente se representarán los datos obtenidos. Sin más, ¡empezamos!

Scopes

Este concepto es muy importante en Dagger ya que definirá hasta cuándo permanecerá viva nuestra dependencia. Entre otros podemos encontrar:

  • @Singleton. La instancia de la dependencia se mantendrá para todo el ciclo de vida de la aplicación. Por lo tanto, si accedemos a dicha instancia siempre accederemos a la misma y no se creará otra. Hay que tener cuidado con el número de singletons que creamos en nuestra aplicación ya que pueden penalizar el rendimiento de la misma.
  • @Reusable. Indica que las instancias se podrán reusar entre componentes pero sin embargo, también estarán disponibles para que el recolector de basura pueda liberarlo.

También podemos definir scopes customizados con el fin de especificar hasta cuándo queremos que nuestras instancias permanezcan “vivas”. Es importante saber que si no establecemos un scope a nuestra instancia, por defecto, se creará una nueva cada vez que se quiera obtener la misma.

Sabiendo esto, podemos crear instancias que estén retenidas en memoria mientras componentes de nuestra app también lo hagan, concretamente vamos a definir @ActivityScope para nuestros presenters. De este modo, cuando nuestra activity ya no exista el presenter tampoco existirá mejorando el uso de memoria y evitando memory leaks.

HomePresenter, empezamos a extender nuestro BasePresenter

Tendrá un método público que se llamará loadData, será el encargado de ejecutar el job en el cuál se cargarán los datos del servicio. Además, una vez que los datos se hayan parseado se pasarán a la vista para su posterior representación.

En cuanto a la representación de los datos, no vamos a tomar tiempo aquí ya que ya se vió en el post de Retrofit y JobQueue.

Hemos añadido un método llamado getContext() que retornará el contexto de la vista con el fin de que el presenter esté completamente abstraído del SDK de Android.

HomeView. Definición de la interfaz de nuestra vista.

Esta interfaz es la que debe cumplir nuestro fragment ya que será el punte de cominicación entre el Presenter y la Vista. Los métodos son autoexplicativos por lo que no será necesario detallarlos.

HomeModule

Será el encargado de proporcionar la instancia del HomePresenter y tendrá el scope definido anteriormente denominado como @ActivityScope con el fin de limitar su estancia en la memoria del dispositivo.

Podemos ver una nueva keyword, se trata de “internal” no es más que un modificador de visibilidad (ya hemos visto public, private y protected) que permite que el método sea visible a nivel de módulo.

HomeComponent

Tendrá el método encargado de inyectar nuestro fragment para que pueda usar la instancia de su presenter, además como dependencia tendrá AppComponent y y como módulo HomeModule.

HomeFragment

Se trata de nuestro primer fragment que usará las dependencias. En este caso, necesitará la instancia de HomePresenter para la carga de datos. Su implementación será la siguiente:

  • Definición de la variable como lateinit de nuestro presenter, el cuál será instancia de HomePresenter, como hemos explicado anteriormente estas variables indican que una variable se inicializará después de su creación. Es importante saber que si no está inicializada lanzará una excepción.

  • Sobreescribimos la variable layoutResource que contiene el id del layout a cargar en la vista. Esta variable era abstracta en BaseFragment por eso nos obliga a sobreescribirla.

  • initializeView. Es un método abstracto de la clase BaseFragment que se lanza en el momento de la inicialización de la vista, por eso, llamaremos al método loadData de nuestro presenter para que comienze la cargade datos.

  • onFragmentInject. Es otro método abstracto de BaseFragment que será el momento donde inyectamos el fragment y establecemos la vista a nuestro presenter.

Conclusión

Una vez ya tenemos definidos nuestros componentes, módulos, fragments, presenters y jobs, simplemente tenemos que enlazarlos para que nuestra app sea totalmente funcional.

El código está disponible en enlace.

En el principio de estos post no nos centramos en la separación por capas, pero con MVP hemos conseguido separar lógica de vista, al menos, de forma inicial. Resumiendo un poco el contenido de los post anteriores, hemos desarrollado una aplicación en Kotlin que realiza una llamada a servicio y representa los datos usando Dagger2, Retrofit y JobQueue, ¡Casi nada!. Espero que os haya gustado.


Sobre el autor

Francisco Manuel López Jurado   

Apasionado de la tecnología y todo lo que la rodea. Desarrollador Senior Android e iOS.