Xamarin.Forms, anatomía de una app
En el blog he hablado mucho de Xamarin.Forms, pero nunca he explicado cómo es que funciona una app hecha con Forms... pues bien, en este post lo explico. Para este post estaré usando la aplicación Mvvmdex que expliqué en un post pasado.
Comenzando por la estructura en componentes de la aplicación, en el siguiente diagrama se muestra a grandes rasgos las partes que componen una aplicación hecha con Forms, en el diagrama podrás ver que una app se compone de dos tipos de proyecto: el núcleo (en el diagrama tiene la etiqueta Shared Code) y los clientes (iOS, Android y UWP):
Núcleo
En el núcleo es en donde ocurre la mayor parte del trabajo en una app con Forms ya que contiene gran parte de lo que la hace funcionar, incluyendo la interfaz gráfica. Es importante señalar que el hecho de que en el diagrama esté todo agrupado, no necesariamente tiene que ser así, podemos dividir el núcleo en tantos proyectos como sea necesario y conveniente para nuestro desarrollo. Por ejemplo, en mi app Mvvmdex, el núcleo está dividido en tres: Models, ViewModels y Views:
Este tipo de proyecto es usualmente una librería de clases portable, aunque también puede ser un proyecto compartido. Sin importar qué tipo de proyecto sea, debes tener en cuenta las partes fundamentales en el código del núcleo, las cuales son:
Que exista una clase derivada de
Xamarin.Forms.Application
. En el caso de la Mvvmdex esta se encuentra en el archivoApp.xaml.cs
. Esta clase puede ser de solo código o depender de un archivo Xaml asociado.Dentro del constructor de dicha clase establecer la página inicial de nuestra aplicación a través de la propiedad
MainPage
En el template por default la página es creada directamente en el constructor, en mi app, la pagina principal está en un archivo separado.
Así es como se ve en el sistema de archivos y en el explorador de soluciones:
Clientes
Los proyectos clientes son aquellos que "consumen" el núcleo, estos tienden a requerir menos trabajo ya que su expresión más sencilla, su única labor es cargar el núcleo usando código específico de la plataforma. En general la forma de ejecutar la aplicación es similar en todas las plataformas soportadas (Android, iOS y Windows): Primero se carga el inicializa el mecanismo de Xamarin.Forms y después se carga el núcleo de nuestra app. A continuación los detalles:
iOS
En iOS hay tres tareas a realizar:
- Que nuestro
AppDelegate
derive deFormsApplicationDelegate
- Inicializar Forms llamando a
Forms.Init();
, esto debe ser en el método sobreescritoFinishedLaunching
- Finalmente se carga la aplicación con el método
LoadApplication
, pasándole como parámetro una instancia de nuestraApp
Así es como se ve en el sistema de archivos y en el explorador de soluciones:
En esta plataforma de igual manera son tres tareas:
- Que la "
MainActivity
" derive deFormsAppCompatActivity
(o deFormsApplicationActivity
) - Inicializar Forms con
Forms.Init(this, bundle);
, pasandole como parámetros la activity en cuestión y su bundle, la inicialización debe suceder en el métodoOnCreate
- Finalmente se carga la aplicación con el método
LoadApplication
, pasándole como parámetro una instancia de nuestraApp
Así es como se ve en el sistema de archivos y en el explorador de soluciones:
Trabajar con Windows es un poco "complicado", ya que requiere modificar dos archivos:
- En la clase
App
del proyecto de Windows inicializar Forms conForms.Init(e);
, es importante pasarle los argumentos del método como parámetros. Esto debe ocurrir dentro del métodoOnLaunched
. - Ahora, en el archivo
MainPage.xaml
, debemos cambiar el tipo de la página dePage
aWindowsPage
, para esto es necesario añadir un xml namespace - Finalmente, como con los anteriores, se carga la aplicación con el método
LoadApplication
(pasándole como parámetro una instancia de nuestraApp
) dentro del constructor de laMainPage
Así es como se ve en el sistema de archivos y en el explorador de soluciones:
Tal vez esto podrá parecerte muy... innecesario, ya que los templates que trae Xamarin hacen esta tarea por nosotros, sin embargo, yo creo que nunca está de más saber cómo es que funcionan las cosas, además de que tu aplicación exija que este proceso de ejecución de la aplicación se realice de una manera distinta a la forma por default de Xamarin.Forms, por ejemplo para recibir archivos en una aplicación.