Está en la página 1de 131

23/2/2020 Jim Bennett

Página 1

Crear aplicaciones móviles nativas multiplataforma

Jim Bennett
F OREWORD POR James Montemagno

MANNING

www.allitebooks.com

Página 2

Un adelanto ...
Al crear aplicaciones de Xamarin utilizando el patrón de diseño MVVM, usted también puede reutilizar
80% de su código en iOS y Android.

iOS Androide

C# C#
App
capa
C#

C#
Capa de interfaz de usuario C# Ver

https://translate.googleusercontent.com/translate_f 1/131
23/2/2020 Jim Bennett
Unión

Lógica de la interfaz de usuario Ver


C#
capa modelo

Negocio
C# Modelo
capa lógica

Escogiendo el hilo correcto ...


Todos odiamos las aplicaciones móviles que no responden. Aquí se explica cómo decidir qué ejecutar
en un hilo de fondo.

¿Esto usa ¿Esto toma UI hilo o


Haz esto No No No
recursos externos más de 100 ms antecedentes
involucrar a la interfaz de usuario?
(DB, web)? en un dispositivo lento? hilo

si si si

Antecedentes Antecedentes
Subproceso de interfaz de usuario
hilo hilo

www.allitebooks.com

Página 3

Xamarin en acción
C REATE CRUZ NATIVA - PLATAFORMA
APLICACIONES MÓVILES

JIM BENNETT

MANNING
S HELTER I SLAND

https://translate.googleusercontent.com/translate_f 2/131
23/2/2020 Jim Bennett

www.allitebooks.com

Página 4

Para información en línea y pedidos de este y otros libros de Manning, visite


www.manning.com. El editor ofrece descuentos en este libro cuando se ordena en cantidad.
Para obtener más información, póngase en contacto

Departamento de ventas especiales


Manning Publications Co.
20 Baldwin Road
PO Box 761
Shelter Island, NY 11964
Correo electrónico: orders@manning.com

© 2018 por Manning Publications Co. Todos los derechos reservados.

Ninguna parte de esta publicación puede reproducirse, almacenarse en un sistema de recuperación o transmitirse en
de cualquier forma o por medios electrónicos, mecánicos, fotocopias o de otro tipo, sin previo aviso
permiso del editor.

Muchas de las designaciones utilizadas por fabricantes y vendedores para distinguir sus productos son
reclamado como marcas registradas. Donde aparecen esas designaciones en el libro, y Manning
Publicaciones estaba al tanto de un reclamo de marca registrada, las designaciones se han impreso en mayúsculas iniciales
o todos los gorros.

Reconociendo la importancia de preservar lo que se ha escrito, es política de Manning tener


Los libros que publicamos están impresos en papel libre de ácido, y hacemos todo lo posible para lograrlo.
Reconociendo también nuestra responsabilidad de conservar los recursos de nuestro planeta, Manning books
se imprimen en papel reciclado y procesado al menos en un 15 por ciento sin el uso de
cloro elemental

Manning Publications Co. Editora de desarrollo: Elesha Hyde


20 Baldwin Road Editor de revisión: Aleksandar Dragosavljevic
PO Box 761 Editor de desarrollo técnico: Gary Park
Shelter Island, NY 11964 Editor del proyecto: Kevin Sullivan
Revisor: Andy Carroll
Corrector de pruebas: Corbin Collins
Corrector técnico: Tomasz Cielecki
Tipografía: Dottie Marsico
Ilustrador: April Milne
Diseñador de portada: Marija Tudor

ISBN 9781617294389
Impreso en los Estados Unidos de América
1 2 3 4 5 6 7 8 9 10 - EBM - 23 22 21 20 19 18

www.allitebooks.com

Página 5

Para los asombrosos Nat y Evie,


por su inquebrantable amor y apoyo mientras estaba pegado a mi computadora portátil.

https://translate.googleusercontent.com/translate_f 3/131
23/2/2020 Jim Bennett

www.allitebooks.com

Página 6

www.allitebooks.com

Página 7

https://translate.googleusercontent.com/translate_f 4/131
23/2/2020 Jim Bennett

contenidos breves
P ARTE 1 G INTRODUCCIÓN COMENZÓ CON X AMARIN .................................... 1
1■ Introducción de aplicaciones nativas multiplataforma con Xamarin 3
2■ Hola MVVM: crear una plataforma cruzada simple
aplicación que usa MVVM 25
3■ MVVM: el patrón de diseño de modelo vista-vista-modelo 50
4■ Hola de nuevo, MVVM: comprender y mejorar nuestro sencillo
Aplicación MVVM 81
5■ ¿Qué estamos esperando (a)? Una introducción a multihilo
para aplicaciones Xamarin 113

P ART 2 B APLICACIONES DE UILDING ............................................ ................. 153


6■ Diseño de aplicaciones multiplataforma MVVM 155
7■ Construcción de modelos multiplataforma 195
8■ Construcción de modelos de vista multiplataforma 241
9■ Construyendo vistas simples de Android 288
10 ■ Creación de vistas de Android más avanzadas 319
11 ■ Creación de vistas simples de iOS 345
12 ■ Creación de vistas de iOS más avanzadas 385

www.allitebooks.com

Página 8
vi CONTENIDOS BREVES

P ART 3 F ROM CÓDIGO DE TRABAJO A LA TIENDA ........................... 409


13 ■ Ejecución de aplicaciones móviles en dispositivos físicos 411
14 ■ Probar aplicaciones móviles con Xamarin UITest 436
15 ■ Uso de App Center para compilar, probar y monitorear aplicaciones 467
16 ■ Implementación de aplicaciones en beta testers y tiendas 505

https://translate.googleusercontent.com/translate_f 5/131
23/2/2020 Jim Bennett

www.allitebooks.com

Página 9

contenido
prólogo xv
prefacio xvii
agradecimientos xix
sobre este libro xxi
sobre la ilustración de la portada xxvi

P ARTE 1 G INTRODUCCIÓN COMENZÓ CON X AMARIN .................... 1

1 Introducción de aplicaciones nativas multiplataforma con Xamarin 3


1.1 Presentación de las aplicaciones móviles de Xamarin 4
Aplicaciones nativas específicas del proveedor
Córdoba 56 Nativo de Xamarin

aplicaciones 7Xamarin.Forms 10
■ Herramientas para desarrolladores de Xamarin 12

Ciclo de vida de desarrollo optimizado para dispositivos móviles 13


1.2 Crear aplicaciones móviles con calidad de producción 14
Diseño 15 ■ Desarrollar 17 ■ Prueba 18 ■ Build 21
Distribuir 22 ■ Monitor 22

1.3 Enjuague y repita ... 23

2 Holaaplicación
MVVM: crear una
que usa plataforma
MVVM 25 cruzada simple
2.1 ¿Qué son los patrones de diseño de la interfaz de usuario? 26
2.2 MVVM: el patrón de diseño para las aplicaciones de Xamarin 27
2.3 ¿Qué es el código multiplataforma? 31
Bibliotecas de clases de .NET Standard 32

vii

www.allitebooks.com

Página 10
viii CONTENIDO

2.4 Introducción: creación de su primera solución 34


Requisitos: qué hardware o software necesita para cada
¿plataforma móvil? 35 Crear la solución 36
■ Que tenemos

¿Acaba de crear? 42 Creación y ejecución de las aplicaciones 43


2.5 ¿Es realmente una aplicación multiplataforma? 47

https://translate.googleusercontent.com/translate_f 6/131
23/2/2020 Jim Bennett
3.1 La capa modelo 52
3 MVVM: el patrón de diseño de modelo vista-vista-modelo 50
3.2 La capa del modelo de vista 53
Estado y comportamiento 54 Conversión de valor 65 ■ ■ Testabilidad 67
3.3 La capa de vista 68
3.4 Encuadernación 69
Fuente y objetivo 69 ■ Modo de enlace 70 ■ Enlace no es
multiplataforma 70 ■ Convertidores de valor 72
3.5 La capa de aplicación 74
3.6 Navegación 75
Ver primero 76 ■ Ver modelo – primero 76 ■ ¿Cuál usar? 78
3.7 Revisión de la aplicación de calculadora de raíz cuadrada 78

4 Holamejorando
de nuevo,nuestra
MVVM:sencilla
comprensión y MVVM 81
aplicación
4.1 Una inmersión más profunda en nuestro Hello Cross-Platform World
aplicación 82
El modelo 82 ■ El modelo de vista 82 ■ La aplicación
capa 83 ■ La vista 84

4.2 Ampliación de nuestra aplicación Hello World 92


Uso de complementos de .NET Standard para acceder al código específico del dispositivo 93
Instalación del complemento de texto a voz Xamarin 95 Agregar el ■

código multiplataforma 97 Inversión de control 98 ■ Cableando el ■

Android UI 105 Cableado de la IU 106 de iOS


5 ¿Quéparaestamos esperando
aplicaciones (a)? Una
Xamarin 113 introducción a multihilo
5.1 ¿Por qué necesitamos código multiproceso? 114
5.2 ¿Qué son los hilos? 117
Comprar café 117 ■ Entonces, ¿qué es un hilo? 120 Un rápido ■

resumen 121

www.allitebooks.com

Página 11
CONTENIDO ix

5.3 Subproceso de interfaz de usuario y subprocesos de fondo 122


El hilo de la interfaz de usuario
Subprocesos
122 de fondo 124 ■

5.4 Uso de tareas para ejecutar código en segundo plano 125


Tarea y Tarea <T> 126 ■ Encadenamiento de tareas 128
5.5 Resultados de la tarea 130
Sondeo para ver si la tarea ha terminado 130 Esperando en el ■

tarea 130 ■ Obteniendo el resultado de una continuación 131


Excepciones de tareas 132
5.6 Actualización de la IU 133
El planificador de tareas de IU 135Usando el poder de MVVM 137 ■

5.7 Asíncrono y espera 139


Las palabras clave asíncronas y aguardadas Escribiendo
139 tu propio asíncrono ■

métodos 143 Comandos asíncronos 147


5.8 Haga que su aplicación se sienta receptiva 148


5.9 Es hora de empezar a construir cosas 150

P ART 2 B APLICACIONES DE UILDING ............................................ ..153

6 Diseño de aplicaciones MVVM multiplataforma 155


6.1 Introducción al diseño de una aplicación multiplataforma 156
6.2 Diseño de la IU y los flujos de usuarios 159
SquareRt: una aplicación sencilla para calcular raíces cuadradas 159
Countr: una aplicación para contar varias cosas 161
Definición de flujos de usuarios e interfaces de usuario 162
6.3 Arquitectura de la aplicación 164
Cual capa 164 ■ Cual hilo? 167 ■ Código de mapeo a
capas e hilos 169
6.4 Crear las soluciones 171
6.5 Propiedades de aplicación 172
Manifiesto de Android 172 ■ iOS info.plist 175

6.6 SDK versiones 177


Versiones de Android SDK y el administrador de SDK 179

https://translate.googleusercontent.com/translate_f 7/131
23/2/2020 Jim Bennett
iOS SDK versiones 185
6.7 Vinculación 187
Vinculación de las aplicaciones
Opciones
188 de enlazador 189Deteniendo el
■ ■

enlazador de hacer demasiado 191

Pagina 12
X CONTENIDO

7 Construcción de modelos multiplataforma 195


7.1 Construcción de capas de modelos simples 196
7.2 Pruebas unitarias 199
Creación de un proyecto de prueba unitaria
Creando
201 tu primer ■

prueba 205 ¿Qué te dicen estas pruebas? 210


7.3 Construcción de capas de modelos más complejos 211


Servicios, modelos de datos y repositorios 211 Accediendo ■

bases de datos 214 Agregar una capa de servicio 221


Acceso a servicios web 228

7.4 Un resumen rápido 238

8 Construcción de modelos de vista multiplataforma 241


8.1 La capa de modelo de vista 241
La capa de modelo de vista dentro de SquareRt 242 El modelo de vista ■

capa dentro de Countr 244


8.2 Agregar estado y comportamiento a SquareRt 248
Estado dentro de SquareRt 248 ■ Exponer el comportamiento a través de
cambios de propiedad 257
8.3 Agregar estado y comportamiento a Countr 260
Propiedades de valor único 260 Colecciones 262 ■

Exponer el comportamiento usando los comandos 267


Mensajería 272 ■ Navegación 278
8.4 Un resumen rápido 285

9 Creación de vistas simples de Android 288


9.1 Creación de interfaces de usuario de Android 289
Diseño de materiales 289 Archivos de diseño 291 Recursos 292
■ ■

Ubicaciones de recursos 292 Edición de archivos de diseño 293


■ Diseño ■

inflación 298

9.2 Creación del archivo de diseño para SquareRt UI 299


Agregar una barra de herramientas
Agregar299
una imagen 304 Agregar un ■ ■

Control EditText 307 Agregar un resultado TextView control 312


9.3 Construcción de la vista SquareRt 313


¿Qué es una actividad? 313 El ciclo de vida de la actividad 314

Crear una actividad para la vista 315 Ejecutando la aplicación 317


Página 13
CONTENIDO xi

10 Creación de vistas de Android más avanzadas 319


10.1 Construir la interfaz de usuario para Countr 320
Creación de la IU para la vista maestra 320 Recycler vistas 322 ■

Creación de la IU para los elementos de vista de reciclador


Acción
323 flotante ■

botones 326 ■ Crear la IU para la vista de detalles 327


Elementos del menú 328
10.2 Construyendo las actividades de Countr 328
Configuración de vistas de reciclador maestroLa
330
vista detallada 332 ■

Ejecutando la aplicación 334

10.3 Iconos de aplicaciones y pantallas de inicio 336


Iconos de aplicacionesPantallas
336 de lanzamiento 338

11 Creación de vistas simples de iOS 345


11.1 Creación de IU de iOS 346

https://translate.googleusercontent.com/translate_f 8/131
23/2/2020 Jim Bennett
Directrices de interfaz humana para iOS 346 Storyboards 348 ■

Controles 350 Diferentes resoluciones de pantalla 351 Diseño automático


■ ■

con restricciones 353 Recursos de imagen y catálogos de activos 357


Un resumen rápido 359

11.2 Crear el guión gráfico 360 de SquareRt


Agregar nuestro primer controlador de vista 361
Agregar una imagen 363 ■

Agregar un campo de texto 368 Agregar la etiqueta de resultado 371 ■

Ver el diseño en diferentes dispositivos 371 Clases de talla 372 ■

Un resumen rápido 376


11.3 Construcción de la vista SquareRt 376
¿Qué es un controlador de vista? 377 Ver ciclo de vida 377 Creando ■ ■

el controlador de vista 378 Conexión de controles a la vista


controlador 379 Enlace del controlador de vista 381


■ Otro ■

resumen rápido 382 Ejecutando la aplicación 382


12 Creación de vistas de iOS más avanzadas 385


12.1 Construir la interfaz de usuario y los controladores de vista para Countr 385
Creación de la IU para la vista maestra 386 Barras de navegación y ■

botones 393 Creación de la IU para la vista detallada 395


Un resumen rápido 397 Ejecutando la aplicación 398 ■

12.2 Iconos de aplicaciones y pantallas de inicio 399


Iconos de aplicacionesPantallas
399 de lanzamiento 402 ■

12.3 Preparar las aplicaciones para la producción 406

Página 14
xii CONTENIDO

P ART 3 F ROM CÓDIGO DE TRABAJO A LA TIENDA ............ 409

13 Ejecución de aplicaciones móviles en dispositivos físicos 411


13.1 Ejecutar aplicaciones de Android en un dispositivo real 412
13.2 Firma de aplicaciones de Android para publicar 415
Configuración del nombre del paquete Tiendas
415 de llaves 416 ■

Crear almacenes de claves y compilaciones de compilación 416


13.3 Ejecutar aplicaciones de iOS en un dispositivo real 420
¿Qué es un perfil de aprovisionamiento? 420 Identificadores de paquete 421 ■

Crear una aplicación ficticia en Xcode 421 Ejecutando su aplicación en ■

un dispositivo físico 424


13.4 Creación de perfiles de aprovisionamiento de iOS 424
Certificados 425 ID de aplicaciones 429
■ Dispositivos 429 ■

Perfiles de aprovisionamiento 432Ejecutando su aplicación usando el ■

nuevo perfil de aprovisionamiento 433Solución de problemas 434 ■

14 Prueba de aplicaciones móviles con Xamarin UITest 436


14.1 Introducción a las pruebas de IU 436
Escribir pruebas de IU con Xamarin UITest 437 Configurando su ■

aplicación para pruebas de IUEjecución


439 de las pruebas autogeneradas 443 ■

14.2 Pruebas de escritura 448


El árbol visual 449 El REPL 450 ■ Identificando ■

controles 452 ■ Tocando el botón Agregar 454 Entrando ■

texto 455 ■ Encontrar controles basados en su texto 456


Afirmaciones 457 Probar su prueba rompiendo cosas 460

14.3 Pruebas que incrementan un contador 462


14.4 La interfaz de la aplicación y las consultas de la aplicación 463
La interfaz IApp 464 ■ Consultas 465

15 Uso de App Center para compilar, probar y monitorear aplicaciones 467


15.1 Presentación de Visual Studio App Center 468
Apps 469 ■ Usuarios y organizaciones 470 ■ API 470
CLI 471 ■ Obteniendo ayuda 471
15.2 Configuración de compilaciones 471
Creación de su primera aplicación App Center 472
Configurando el ■

Android build 473 Configuración de la compilación 476 de iOS


15.3 Prueba de sus aplicaciones usando Test Cloud 479


¿Qué es Test Cloud? 479 Preparando tus aplicaciones para ser

probado 479
■ ■Creación de una configuración de ejecución de prueba 481

https://translate.googleusercontent.com/translate_f 9/131
23/2/2020 Jim Bennett

Página 15
CONTENIDO xiii

Ejecución de pruebas desde la línea de comando 484


Ver los resultados de la prueba en App Center 487
15.4 Análisis e informes de fallos 491
Agregar los SDK de App Center 491 ■ Comprensión
su audiencia 493 ■ Agregar seguimiento de eventos 497
Choque reportando 500

16 Implementación de aplicaciones en beta testers y tiendas 505


16.1 Distribución de aplicaciones de Android a beta testers 506
Habilitación de la distribución de aplicaciones
Actualizaciones
506 ■ automáticas 511
16.2 Publicación de aplicaciones de Android en la tienda Google Play 514
Configuración de su cuenta 514 ■ Crear su aplicación 514
Tiendas alternativas 522

16.3 Distribución de aplicaciones iOS a beta testers 523


Habilitación de la distribución de aplicaciones
Actualizaciones
523 ■ automáticas 527
16.4 Publicación de aplicaciones de iOS en la tienda de aplicaciones de Apple 530
Aprovisionando su aplicación para publicar 530 ■ Configuración
su aplicación 530

Apéndice A UI flujos y subprocesos para SquareRt y Countr 543


apéndice B Uso de MVVM Light en lugar de MvvmCross 548
índice 565

Página 16

https://translate.googleusercontent.com/translate_f 10/131
23/2/2020 Jim Bennett

Página 17

prefacio
Cuando Jim me dijo que estaba escribiendo un libro sobre Xamarin centrado en la arquitectura
En realidad, el diseño, las pruebas y las mejores prácticas, no podría haber estado más emocionado. yo sabía
Fue el autor perfecto para este estilo de libro. La primera vez que interactué con
Jim, ambos estábamos creando enlaces C # alrededor de bibliotecas de balizas Bluetooth para iOS
y Android Supe de inmediato que nos haríamos buenos amigos, y me alegro de que sea
se unió a Microsoft como uno de nuestros defensores de desarrolladores para continuar con todo el gran trabajo
lo estaba haciendo en la comunidad.
Xamarin in Action es un recurso que desearía haber tenido a mi lado cuando comenzaba
Desarrollo móvil multiplataforma nativo con Xamarin. Este libro te acompaña
a través de los fundamentos clave de lo que es Xamarin y cómo funciona la tecnología en
Visual Studio, pero también lo guía a través de las mejores prácticas en la producción de edificios.
Aplicaciones móviles de calidad. Desde el diseño hasta la arquitectura y la implementación, al final de
este libro tendrá una comprensión completa del desarrollo móvil con Xamarin y
seguramente me he enamorado tanto como yo.
Cuando Jim me preguntó si escribiría un prólogo para su libro, comencé a leer
En los capítulos, me trajo de vuelta a cuando descubrí a Xamarin por primera vez. Esta
puede estar donde está ahora, preparándose para comenzar su desarrollo móvil
carrera. No podría pensar en una mejor manera de presentar a Xamarin en Acción que compartiendo
mi viaje de Xamarin contigo.
Puedo recordar vívidamente el momento que me hizo querer convertirme en un desarrollador móvil.
oper, cambiando mi vida para siempre. Era el otoño de 2010, y estaba asistiendo a mi primer
conferencia de desarrolladores, la Conferencia de Desarrolladores Profesionales en Redmond, Washington
ington, en la sede de Microsoft. Mientras estuve allí, me presentaron a Azure, el futuro
de computación en la nube, y me entregaron mi primer teléfono inteligente. Esta pequeña supercomputadora

xv

Página 18
xvi PREFACIO

https://translate.googleusercontent.com/translate_f 11/131
23/2/2020 Jim Bennett
No solo cabe en mi bolsillo, sino que también me permite crear aplicaciones completas en C #
de Visual Studio que podría enviar a personas de todo el mundo. Me voló la cabeza. En
En ese instante, supe que había terminado de escribir software de impresora y que necesitaba mudarme a Seattle
estar más cerca de la acción.
Antes de darme cuenta, había aceptado un trabajo en una pequeña empresa, moví mi vida a través del mundo.
país, y comencé mi papel como el único desarrollador móvil. En mi primer día, me encargaron
con la creación de aplicaciones nativas de iOS, Android y Windows en solo dos meses. yo
Recuerdo congelarme de inmediato, mientras trataba de averiguar qué había conseguido.
y cómo iba a lograr esto como desarrollador de C # que no sabía
Objective-C o Java. Sabía que tendría que encontrar un marco multiplataforma si fuera
va a tener éxito, y que necesitaría integrarse en mi desarrollo actual
ment workflow y herramientas y, por supuesto, ser impulsado por C #. Esto fue cuando descubrí
Ered la plataforma Xamarin. No perdí el tiempo descargando las herramientas y
¡Comencé a crear mis primeras aplicaciones nativas de iOS y Android en C # y Visual Studio!
Desde mi primer Archivo> Nueva experiencia, estaba enamorado de Xamarin. Me dio
todo lo que podría pedir en una plataforma, incluido el rendimiento nativo, acceso a cada
API nativa única en C #, y una interfaz de usuario nativa completa que podría crear directamente
Estudio visual. Xamarin realmente hizo que la creación de aplicaciones nativas multiplataforma sea rápida, fácil y
divertido, y nunca miré hacia atrás. Después de enviar con éxito esas aplicaciones iniciales en solo unas pocas
meses (y varios más en los próximos años), estaba tan enamorado de Xamarin que
Acepté un trabajo en la empresa como defensor de desarrolladores, para poder enfocar todo mi
energía para ayudar a los desarrolladores de todo el mundo a transformar sus carreras con el
poder de Xamarin.
No es una hipérbole cuando digo que me encanta esta tecnología y sé que
puede transformar su negocio para ser más productivo y ágil al crear aplicaciones móviles
cationes Incluso tiene el poder de cambiar toda tu carrera. Soy prueba viviente.

J AMES M ONTEMAGNO
Gerente Principal del Programa,
Herramientas para desarrolladores móviles, Microsoft

Página 19

prefacio
He estado involucrado en tecnología la mayor parte de mi vida, y cada año es más emocionante para un
tecnólogo que el anterior. Las innovaciones siguen llegando cada vez más rápido, haciéndolo algo-
veces difícil (y siempre costoso) mantener el ritmo. Una de las innovaciones más emocionantes.
de la última década ha sido el auge del teléfono inteligente. El mundo de la tecnología
cambió el día en que Steve Jobs anunció el iPhone, y ha estado pasando de
fuerza a fuerza desde entonces. He sido un ávido usuario de iPhone desde el principio, y yo
incluso escribió un par de aplicaciones usando Objective-C durante los primeros años del iPhone. los
Lo más importante que aprendí de esa experiencia fue que escribir aplicaciones móviles es genial, pero
Usar Objective-C es doloroso.
Avancé unos años y fui un desarrollador aburrido de C #. Había estado construyendo comercio
sistemas durante años, aplicaciones de escritorio diseñadas para ayudar a otras personas a ganar mucho dinero
con tecnología poco emocionante, y necesitaba un cambio. Al comienzo de mi carrera estaba pas-
Sionate sobre la codificación, escribir código en mi tiempo libre y devorar libros y entrenar-
cursos de ing. Después de varios años en finanzas, esa pasión se estaba muriendo. Miré

https://translate.googleusercontent.com/translate_f 12/131
23/2/2020 Jim Bennett
busqué algo que lo volviera a encender, y encontré la respuesta: Xamarin.
Había pasado años aprendiendo C #, y con Xamarin podría usar esas habilidades para construir
Aplicaciones móviles para iOS y Android. Ya no tendría que escribir Objective-C
código para iOS y código Java para Android. El mundo del desarrollo móvil había sido
abierto a desarrolladores como yo usando C #, un lenguaje que no solo era muy cómodo
con, pero también disfruté activamente usando. Decidí que Xamarin era la tecnología para
yo, me compré una licencia, me inscribí en la Universidad Xamarin, renuncié a mi trabajo y gasté
cuatro meses en un espacio de trabajo conjunto aprendiendo Xamarin. Estaba enganchado y desde entonces
No he mirado hacia atrás. Me ha apasionado tanto la tecnología que quería contar
al mundo lo fácil que es crear aplicaciones móviles multiplataforma.

xvii

Página 20
xviii PREFACIO

Una pregunta que seguía surgiendo en la comunidad era: “¿Cómo construyo un


aplicación de calidad de producción? Hay muchas guías excelentes sobre cómo usar iOS y
Android SDK, pero no hay documentación de principio a fin sobre cómo pasar de una idea a una
aplicación que funciona, probada y enviada: documentación que aprovecha los patrones de diseño
como MVVM no solo para construir código comprobable, sino también para aprovechar el Xamarin
capacidad más poderosa: la capacidad de compartir grandes porciones de su código entre plataformas
formas Esa fue la inspiración para este libro. Xamarin es una mejor manera de escribir, probar,
monitorear e implementar aplicaciones móviles, y este libro tiene como objetivo mostrarle cómo.

www.allitebooks.com

Página 21

https://translate.googleusercontent.com/translate_f 13/131
23/2/2020 Jim Bennett

expresiones de gratitud
Este libro ha involucrado una gran cantidad de trabajo durante el año pasado y un poco. Pero en
A pesar de las innumerables horas que pasé, nunca habría sucedido sin un montón de
trabajo duro de algunas personas increíbles. Este libro no es la creación de un gran escritor;
en cambio, es el resultado de un desarrollador entusiasta parado sobre los hombros de gigantes,
Y es a estos gigantes a quienes debo una gran cantidad de gracias.
Primero, me gustaría agradecer al equipo de Xamarin por crear un producto que ha entusiasmado
más allá de cualquier tecnología con la que haya trabajado antes, especialmente Miguel de Icaza,
Nat Friedman y Joseph Hill por fundar una compañía tan increíble para crear un
producto asombroso; James Montemagno por patear mi participación con el Xam-
arin comunidad inspirándome a escribir y hablar; Jayme Singleton por su gran
trabaja construyendo la comunidad Xamarin y apoyando a todos sus miembros; y Mikayla
Hutchinson por estar siempre feliz de ayudar sin importar las preguntas tontas que le hago.
En el lado de la comunidad, me gustaría agradecer a la comunidad MVP de Xamarin, pasado y
presente, por darme la bienvenida al redil, estar disponible para responder preguntas y apoyar
portar mi escritura, con un agradecimiento especial a Dave Evans por darme mi primera oportunidad de
hablar en una reunión, un momento decisivo en mi participación comunitaria. Parte de que
ha hecho que este libro sea tan fácil de escribir es el marco increíble que es MvvmCross, así que
quisiera agradecer también al equipo de MvvmCross por su arduo trabajo y apoyo, especialmente
Martijn van Dijk.
Este libro no hubiera sido tan bueno como una décima parte sin el constante apoyo.
puerto, comentarios y enseñanza de mi editor de desarrollo en Manning Publications, Ele-
Sha Hyde. Las técnicas que me has enseñado me han hecho un mejor comunicador,
escritor y mentor, y he apreciado increíblemente su orientación cada vez
hubo un bache en el camino. Espero haberte hecho sentir orgulloso.

xix

Página 22
xx EXPRESIONES DE GRATITUD

También me gustaría agradecer a los revisores que se tomaron el tiempo para leer el manuscrito en varios
etapas en su desarrollo: Andreas Berggren, Davide Fiorentino lo Regio, Dennis Sell-
inger, Eric Sweigart, Gareth van der Berg, Jason Smith, Jesse Liberty, Karthikeyarajan
Rajendran, Krishna Chaitanya Anipindi, Lokeshwar Reddy Vangala, Mario Solomou,
Michael Lund, Narasimha Baliga, Patrick Regan, Philip Taffet, Prabhuti Prakash, Ric-
cardo Moschetti, Richard Lebel, Stefan Hellweger, Steve Atchue, Thomas Overby
Hansen y Zorodzayi Mukuya. Este libro es mucho mejor debido a sus comentarios.
Me gustaría agradecer especialmente a Gary Park y Tomasz Cielecki (otro miembro del
gran equipo de MvvmCross) por su exhaustiva revisión técnica y su constante alimentación
espalda.
Parte de este libro fue escrito mientras se alimentaba de café y panqueques, así que me gustaría
agradezco a Sarah y al equipo de Soulshine en Browns Bay, Nueva Zelanda, por alimentar mi
escribiendo todos los sábados por la mañana. La mayoría de este libro fue escrito mientras trabajaba
para una pequeña pero increíble compañía en Nueva Zelanda llamada EROAD, y me encantaría
agradecerles por apoyar mis esfuerzos, especialmente a Jared Langguth por darme un
oportunidad de escribir aplicaciones Xamarin todo el día, todos los días, y Sam Williams para continuamente
mostrándome el mundo del desarrollo desde una perspectiva diferente.
Finalmente, no hay forma de que este libro pudiera haber sucedido sin el amor y el apoyo.
Puerto de mi familia. Mis padres primero me metieron en la programación a una edad temprana (incluso
ayudando a copiar listas de códigos fuente de ZX Spectrum de libros y revistas), y
siempre me han inspirado a hacer lo mejor en todo lo que hago y a hacer siempre lo que hago
amor. Gracias a los dos por estar allí para mí toda mi vida. Mi mayor agradecimiento tiene que
Ve con mi esposa, Nat, y mi hija, Evie. Nat: gracias por estar a mi lado mientras yo
Seguí mis pasiones a donde sea que nos llevaran, y por apoyar tal
Gran proyecto personal. Evie, gracias por estar emocionado de que papá enseñara
personas para escribir aplicaciones para iPads. Espero que algún día encuentres algo que te entusiasme y
te conduce como el desarrollo móvil de Xamarin me tiene a mí. Los amo a los dos.
Todas las partes buenas de este libro son gracias a estas personas increíbles. Todos los errores
las tomas son mías y solo mías.

https://translate.googleusercontent.com/translate_f 14/131
23/2/2020 Jim Bennett

Página 23

sobre este libro


Xamarin in Action se ha escrito para ayudarlo a crear aplicaciones móviles con calidad de producción:
aplicaciones de cinco estrellas que están bien diseñadas, bien probadas e implementadas en la tienda con ana-
lítica y monitoreo de fallas. Este libro cubre el viaje desde la idea hasta la entrega, garantizando
ing que construyes tus aplicaciones de la manera correcta. No intenta replicar información que es
fácilmente disponible en línea en documentos de API; en cambio, se enfoca en los conceptos de un bien construido
aplicación Xamarin multiplataforma, que reúne toda la información que necesita sin
te estanca

Quién debería leer este libro


Xamarin in Action es para desarrolladores que desean crear aplicaciones móviles multiplataforma utilizando
C #, ya sea porque es un idioma que conocen o porque quieren aprovechar
de las capacidades multiplataforma de Xamarin. Este libro supone una pequeña cantidad de C #
conocimiento, pero todos los desarrolladores de C # desde principiantes hasta avanzados podrán usarlo para
aprende a construir aplicaciones móviles. Incluso si eres un iOS o Android nativo experimentado
desarrollador de aplicaciones que utiliza Objective-C o Java, este libro lo ayudará a realizar la transición fácilmente a
construyendo aplicaciones de Xamarin. La arquitectura subyacente de una aplicación Xamarin es muy diferente.
ent desde una aplicación nativa, y también lo son las tecnologías y herramientas disponibles. Este libro
ayuda a enseñarle cómo crear aplicaciones utilizando una arquitectura multiplataforma y las herramientas
dentro de Visual Studio.

Cómo está organizado este libro


Este libro está dividido en tres partes que cubren 16 capítulos. Parte 1 cubre la arquitectura
conceptos detrás de una aplicación Xamarin multiplataforma bien escrita, con un examen Hello World-
aplicación para comenzar:

xxi

Página 24
xxii SOBRE ESTE LIBRO

▪ El Capítulo 1 discute Xamarin y los beneficios de construir Xamarin móvil


aplicaciones También analiza el ciclo de vida del desarrollo, cubriendo todos los pasos en la construcción
ing aplicaciones móviles de calidad de producción.
▪ El Capítulo 2 comienza observando MVVM (model-view-view model), el patrón de diseño
Tern para construir aplicaciones multiplataforma comprobables y de buena calidad, y luego analiza
La estructura de una aplicación Xamarin. Luego cubre la creación de un Hello World básico
aplicación móvil multiplataforma.
▪ El Capítulo 3 se sumerge en MVVM con más detalle, mirando las diferentes capas de
modelo, a través del modelo de vista, para ver. Luego cubre la capa de aplicación y
Patrones de navegación.
▪ El Capítulo 4 revisa el ejemplo de la aplicación Hello World del capítulo 2, profundizando
sobre cómo se usó el patrón de diseño MVVM para construir la aplicación. Luego mira a
expandir la aplicación usando complementos Xamarin multiplataforma.
▪ El Capítulo 5 se trata de subprocesos múltiples, cubriendo las consideraciones de subprocesos

https://translate.googleusercontent.com/translate_f 15/131
23/2/2020 Jim Bennett
involucrado al crear aplicaciones móviles e introducir async y esperar, una característica
de C # que facilita la creación de código multiproceso limpio y fácil de leer.

La Parte 2 se basa en esta arquitectura y le muestra cómo crear aplicaciones multiplataforma


comenzando con el código multiplataforma y pasando al código de interfaz de usuario específico de la plataforma.
Tomarás un par de ejemplos desde la etapa de diseño hasta el funcionamiento total de iOS
y aplicaciones de Android:
▪ El Capítulo 6 presenta las dos aplicaciones de ejemplo que se construirán a lo largo del
resto de la parte 2. Analiza cómo diseñar una aplicación, considerando qué código entra
qué capa en el patrón de diseño MVVM. Finalmente, cubre la creación de soluciones para
las aplicaciones de ejemplo y analiza el proyecto y las propiedades de la aplicación para un
Aplicación móvil Xamarin.
▪ El Capítulo 7 se centra en la capa del modelo, incluida la construcción de modelos simples,
ing capas de modelo más complejas con servicios y repositorios, y acceso
Bases de datos SQLite y servicios web. También presenta pruebas unitarias, que muestran cómo
Es fácil probar un código bien estructurado.
▪ El Capítulo 8 sube una capa y cubre los modelos de vista. Considera cómo el estado y
el comportamiento está representado, cubriendo propiedades, comandos y valores de conversión
Sion. También muestra cómo probar la lógica de la interfaz de usuario mediante pruebas unitarias.
▪ El Capítulo 9 cubre la vista y las capas de aplicación e inicia el proceso de compilación
ing la versión de Android de una de las aplicaciones de ejemplo. Cubre el recurso de Android
archivos, diseños, controles de IU y actividades.
▪ El Capítulo 10 se centra en el segundo ejemplo de aplicaciones de Android, que abarca el reciclaje
vistas de escritorio para mostrar listas de datos y navegación multipantalla. Luego muestra
cómo agregar esmalte a una aplicación creando íconos de aplicaciones y pantallas de presentación.
▪ El Capítulo 11 se mueve de Android a iOS, trabajando en la aplicación y vista
capas de la primera aplicación de ejemplo, que cubren controladores de vista, controles de interfaz de usuario, story-
tableros, y diseño automático y restricciones.

Página 25
SOBRE ESTE LIBRO xxiii

▪ El Capítulo 12 cubre cómo construir la segunda aplicación iOS de ejemplo, mirando la tabla
vistas y navegación multipantalla. Luego cubre íconos de aplicaciones y pantallas de inicio.

La Parte 3 cubre la preparación de una aplicación de trabajo lista para producción y su envío a los usuarios:
▪ El Capítulo 13 analiza cómo ejecutar aplicaciones en dispositivos reales, incluida la configuración
Dispositivos Android para desarrolladores, configuración de dispositivos iOS y generación de iOS
perfiles de aprovisionamiento.
▪ El Capítulo 14 cubre las pruebas de IU, la capacidad de escribir y ejecutar pruebas automatizadas que
interactúa con tu aplicación como lo haría una persona real.
▪ El Capítulo 15 presenta Visual Studio App Center, que muestra cómo se puede usar para
cree sus aplicaciones, ejecute pruebas de IU contra dispositivos en la nube y configure sus aplicaciones
para rastrear información de uso y bloqueos.
▪ El Capítulo 16 cubre la etapa final del viaje de una aplicación: entrega a los usuarios. Parece
al usar App Center para proporcionar versiones de prueba beta a usuarios seleccionados y luego muestra
cómo finalmente publicar aplicaciones en Google Play Store y Apple App Store.

Este libro es secuencial, con capítulos posteriores basados en conceptos explicados en


capítulos viciosos. Te lleva en un viaje desde la idea, a través de conceptos arquitectónicos, hasta
construyendo cada capa, y finalmente probando y publicando su aplicación. Lo encontraras
es más fácil leer las dos primeras partes de principio a fin, en lugar de entrar y salir
diferentes capítulos La Parte 3 se puede leer fuera de servicio, según sus necesidades.

Sobre el código
Este libro contiene muchos ejemplos de código fuente, tanto en listados numerados como en
en línea con el texto normal. En ambos casos, el código fuente está formateado en un ancho fijo
fuente como esta para separarlo del texto ordinario. En algunos casos, la fuente original.
el código ha sido reformateado; He agregado saltos de línea y he revisado la sangría para
acomodar el espacio de página disponible en el libro. En casos raros, incluso esto no era
suficiente, y los listados incluyen marcadores de continuación de línea ➥ . Además, comentarios en
el código fuente a menudo se ha eliminado de los listados cuando se describe el código
en el texto. Las anotaciones de código acompañan a muchos de los listados, destacando importantes
conceptos.
El código fuente está disponible para todos los capítulos de este libro, con la excepción de cap-
ters 1 y 3. Cada capítulo tiene una o más soluciones, que muestran la aplicación de ejemplo o
aplicaciones discutidas en ese capítulo, con toda la fuente del capítulo completamente implementada
y trabajando. Por ejemplo, el capítulo 7 tiene dos aplicaciones con capas de modelo que se pueden probar.
utilizando pruebas unitarias, pero no una aplicación ejecutable. En el capítulo 9, se ejecutará la primera aplicación de ejemplo
y estar trabajando completamente en Android.
Todo el código fuente ha sido probado usando Visual Studio 2017 tanto en Windows
(con la carga de trabajo de Xamarin instalada) y Mac basado en la versión 15.4 publicada
en octubre de 2017. Deberá asegurarse de tener el SDK de Android v7.1 o posterior
instalado (El último se instala de forma predeterminada, pero si lo instaló hace mucho tiempo,

https://translate.googleusercontent.com/translate_f 16/131
23/2/2020 Jim Bennett

Page 26
xxiv SOBRE ESTE LIBRO

es posible que deba actualizar su SDK.) También necesitará Xcode 9 o posterior instalado en su
Mac para compilaciones de iOS.
El código fuente de este libro está disponible para su descarga desde la web del editor.
sitio en https://www.manning.com/books/xamarin-in-action .

Requisitos de software y hardware.


El requisito más básico para crear aplicaciones de Xamarin es una computadora que ejecute Visual
Estudio. Los usuarios de Windows necesitarán Visual Studio 2017 con la carga de trabajo de Xamarin
instalado Cuando instala VS2017 con la carga de trabajo de Xamarin, todo lo que necesita
debe instalarse para usted, aunque siempre vale la pena asegurarse de que haya actualizado a
la última versión de Visual Studio y actualizó su SDK de Android a la última versión estable
versión.
Los usuarios de Mac necesitarán la última versión de Visual Studio para Mac instalada. El instalador
debe instalar y configurar todo lo que necesita, con una excepción: Xcode. Tu
necesita instalar Xcode desde Mac App Store. También vale la pena asegurarse de que todo esté listo
hasta la fecha, con las últimas versiones estables de VS para Mac, Android SDK y Xcode
instalado
Si desea crear aplicaciones iOS desde una PC, necesitará acceso a una Mac con Visual
Studio para Mac instalado, ya sea en su red o mediante un servicio en la nube como Macin-
Nube.
Para publicar en las tiendas, necesitará cuentas de desarrollador con Google Play y
Manzana. Estos no son gratis. Actualmente, la cuenta de desarrollador de Google Play es única
tarifa de $ 25, y el programa de desarrolladores de Apple es de $ 99 por año. Podrás correr
su código en emuladores de Android y simuladores de iOS a medida que desarrolla, pero siempre es
Vale la pena tener un hardware real para probar, especialmente cuando se prepara para lanzar al
historias.

Recursos en línea
Si necesita ayuda adicional:
▪ Los foros en https://forums.xamarin.com son un excelente lugar para hacer preguntas.
▪ Hay un vibrante equipo Slack de la comunidad Xamarin al que puedes unirte
https://xamarinchat.herokuapp.com/ , lleno de desarrolladores y soporte de Xamarin
ingenieros
▪ Como siempre, Stack Overflow (https://stackoverflow.com/) tiene las respuestas para la mayoría
cosas que querrás saber, y muchos desarrolladores de Xamarin de primer nivel están en
mano para responder cualquier pregunta adicional que pueda tener.

Foro de libros
La compra de Xamarin in Action incluye acceso gratuito a un foro web privado dirigido por Man-
Publicaciones donde puede hacer comentarios sobre el libro, hacer preguntas técnicas.
y recibir ayuda del autor y de otros usuarios. Para acceder al foro, ve
a https://forums.manning.com/forums/xamarin-in-action . También puedes aprender más

Página 27
SOBRE ESTE LIBRO xxv

sobre los foros de Manning y las reglas de conducta en https: //forums.manning


.com / forum / about .
El compromiso de Manning con nuestros lectores es proporcionar un lugar donde un
diálogo entre lectores individuales y entre lectores y el autor puede tomar
sitio. No es un compromiso con una cantidad específica de participación por parte de
El autor, cuya contribución al foro sigue siendo voluntaria (y no remunerada). Nosotros sugerimos
¡Intenta hacerle al autor algunas preguntas desafiantes para que su interés no se pierda! los
el foro y los archivos de debates anteriores serán accesibles desde el editor
sitio web siempre que el libro esté impreso.

Sobre el Autor
J IM B ENNETT es un Defensor Senior de Desarrolladores en la Nube en Microsoft, especializado en la nube
aplicaciones Xamarin conectadas. Tiene décadas de experiencia en la construcción de computadoras de escritorio y dispositivos móviles.
aplicaciones, principalmente usando C # y otras tecnologías de Microsoft. Durante los últimos cuatro años, él
ha estado muy involucrado en el desarrollo de aplicaciones móviles multiplataforma con Xamarin,
tanto en el trabajo como en proyectos personales. Es un orador habitual en desarrollo móvil.
en reuniones y conferencias, contribuye al código abierto, y bloguea y evangeliza
conoce a Xamarin cada vez que puede. Es un ex MVP de Xamarin y Microsoft, es pas-
Sionate sobre compartir conocimiento y ayudar a otros a aprender, y cuando él no
jugando con su pequeña hija, está feliz de pasar horas discutiendo sobre desarrollo móvil
Opte por la comida tailandesa y la buena cerveza o whisky.

https://translate.googleusercontent.com/translate_f 17/131
23/2/2020 Jim Bennett

Página 28

sobre la ilustración de la portada


La ilustración en la portada de Xamarin in Action lleva el título "Bostandji bachi".
La traducción literal es "jardinero jefe", pero los Bostandjis del sultán turco tenían
poderes y responsabilidades que van mucho más allá de los jardines del sultán hasta sus palacios y
supervisando a la policía de la capital. La ilustración está tomada de una colección de cos-
tumes of the Ottoman Empire publicados el 1 de enero de 1802 por William Miller de Old
Bond Street, Londres. Falta la página de título de la colección, y hasta ahora hemos
sido incapaz de rastrearlo. La tabla de contenido del libro identifica las figuras en
tanto en inglés como en francés, y cada ilustración también lleva los nombres de dos artistas que
trabajaron en ello, los cuales sin duda se sorprenderían de encontrar su arte adornando el
portada de un libro de programación de computadoras 200 años después.
La colección fue comprada por un editor de Manning en un mercado de pulgas anticuario en
el "Garaje" en West 26th Street en Manhattan. El vendedor era estadounidense con sede en
Ankara, Turquía, y la transacción tuvo lugar justo cuando estaba empacando su puesto para el
día. El editor de Manning no tenía en su persona la cantidad sustancial de efectivo que
fue requerido para la compra, y una tarjeta de crédito y un cheque fueron cortésmente girados
abajo. Con el vendedor volando de regreso a Ankara esa noche, la situación parecía desesperada.
¿Cuál fue la solución? Resultó ser nada más que un anticuado verbal
acuerdo sellado con un apretón de manos. El vendedor propuso que el dinero sea transferido
a él por cable, y el editor salió con la información del banco en una hoja de papel
y el portafolio de imágenes debajo de su brazo. No hace falta decir que transferimos los fondos
al día siguiente, y seguimos agradecidos e impresionados por la confianza de esta persona desconocida en uno de
nosotros. Recuerda algo que podría haber sucedido hace mucho tiempo.
Las imágenes de la colección Otomana, como las otras ilustraciones que aparecen
en las portadas de Manning, da vida a la riqueza y variedad de costumbres de vestir de dos

xxvi

Página 29
SOBRE LA ILUSTRACIÓN DE LA CUBIERTA xxvii

https://translate.googleusercontent.com/translate_f 18/131
23/2/2020 Jim Bennett
hace siglos. Recuerdan la sensación de aislamiento y distancia de ese período, y de
cualquier otro período histórico, excepto nuestro propio presente hipercinético. Los códigos de vestimenta tienen
sin duda cambió desde entonces, y la diversidad por región, tan rica en ese momento, se ha desvanecido
lejos. Ahora a menudo es difícil distinguir al habitante de un continente del de otro.
Quizás, visto de manera optimista, hemos cambiado una diversidad cultural y visual por más
Vida personal variada. O una vida intelectual y técnica más variada e interesante.
En Manning celebramos la inventiva, la iniciativa y, sí, la diversión de
negocios informáticos con portadas de libros basadas en la rica diversidad de la vida regional como
fue hace dos siglos, revivido por las imágenes de esta colección.

Página 30

https://translate.googleusercontent.com/translate_f 19/131
23/2/2020 Jim Bennett

Page 31

Parte 1

Empezando
con Xamarin

La forma tradicional de crear una aplicación móvil es escribirla dos veces: una vez en Objec-
tive-C o Swift para iOS, y luego nuevamente en Java para Android. Este es un gran desperdicio de
tiempo, duplicando el código en dos idiomas. Por suerte algunos de los más innovadores
Los ingenieros del mundo (según la revista Time ) tienen una solución: Xamarin.
Xamarin es una plataforma de Microsoft que te permite construir y enviar iOS
y aplicaciones de Android que usan .NET. También es parte de un próspero ecosistema móvil.
que abarca todo, desde recursos en la nube específicos para dispositivos móviles de Microsoft, DevOps
herramientas y una gran comunidad de software de código abierto. En su forma más básica, es una forma
usar el mismo idioma y tecnología en iOS y Android, lo que le permite
para reutilizar grandes cantidades de código y bibliotecas de terceros en dos muy diferentes
plataformas móviles Las mejores prácticas en torno a Xamarin se centran en mantener
Esta cantidad de código compartido lo más grande posible.
Esta primera parte del libro cubre los conceptos arquitectónicos detrás de un pozo.
aplicación Xamarin multiplataforma escrita, centrada en el MVVM increíblemente popular
patrón de diseño. Una buena arquitectura lo ayudará a reutilizar la mayor cantidad de código posible,
vale la pena invertir el tiempo para aprender estos conceptos, evitando perder el tiempo
escribir franjas de código dos veces. Patrones como MVVM le permiten probar su código
más rápido y más fácil usando pruebas unitarias, detectando errores al principio del ciclo de desarrollo
y reduciendo el tiempo de prueba manual (y corrección de errores) más abajo en el desarrollo
ciclo de opciones. Estas son las bases que necesitará para construir calidad de producción
aplicaciones móviles.

Página 32
2 P ART 1 Comenzando con Xamarin

El Capítulo 1 comienza discutiendo sobre Xamarin y los beneficios de construir Xamarin


aplicaciones móviles. También analiza el ciclo de vida del desarrollo, cubriendo todos los pasos en la construcción
ing aplicaciones móviles de calidad de producción.
El Capítulo 2 analiza el patrón de diseño MVVM como una forma de aumentar la reutilización de su código,
y para construir una aplicación comprobada y bien diseñada. Luego cubre la creación de un Hello
Aplicación mundial que utiliza un marco MVVM popular.
El Capítulo 3 se sumerge en MVVM con más detalle, mirando las diferentes capas de

https://translate.googleusercontent.com/translate_f 20/131
23/2/2020 Jim Bennett
modelo, a través del modelo de vista, para ver. Luego cubre la capa de aplicación y navega-
Patrones
El Capítulo 4 revisa el ejemplo de la aplicación Hello World del capítulo 2, profundizando en
cómo se usó el patrón de diseño MVVM para construir la aplicación. Luego se ve en expansión
la aplicación, utilizando complementos multiplataforma Xamarin.
El capítulo 5 trata sobre el subprocesamiento múltiple y cubre las consideraciones de subprocesamiento.
involucrado en la creación de aplicaciones móviles. También presenta async y wait, una característica de C #
eso hace que sea muy fácil construir código multiproceso limpio y fácil de leer.

Page 33

1
multiplataforma nativa
aplicaciones con Xamarin

Introducción
Este capítulo cubre
▪ Qué es una aplicación Xamarin
▪ El ciclo de vida de desarrollo optimizado para dispositivos móviles.
▪ Creación de aplicaciones multiplataforma listas para producción

En el año 2000, Microsoft anunció un nuevo marco de software llamado .NET, junto con
con un nuevo lenguaje de programación llamado C #. No mucho después de esto, una compañía llamó
Ximian (fundado por Miguel de Icaza y Nat Friedman) comenzó a trabajar en Mono,
una implementación gratuita de .NET framework y el compilador de C # que podría ejecutarse
en Linux
Avance rápido 16 años, y Nat Friedman está parado en el escenario en el Xamarin
Conferencia Evolve dando la charla principal, físicamente frente a mil seiscientos

https://translate.googleusercontent.com/translate_f 21/131
23/2/2020 Jim Bennett
desarrolladores móviles y prácticamente frente a decenas de miles más. El esta hablando
sobre cómo Xamarin permite un ciclo de vida de desarrollo optimizado para dispositivos móviles. Xamarin
(la compañía que surgió de las cenizas de Ximian y que proporciona herramientas y
Microsoft acababa de comprar tecnología para crear aplicaciones móviles multiplataforma)

34
44 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

por un rumoreado medio billón de dólares, y se había convertido en una parte clave de Microsoft
Estrategia "móvil primero, nube primero".
Xamarin es ahora un término bien conocido entre la comunidad de desarrolladores móviles, y
está comenzando a ser bien conocido en otros círculos de desarrolladores basados en Microsoft. Pero que hacer
queremos decir cuando hablamos de aplicaciones móviles de Xamarin, y qué nos da Xamarin
por encima y más allá de otras herramientas?

1.1 Presentamos las aplicaciones móviles de Xamarin


Para ver realmente los beneficios de las aplicaciones móviles de Xamarin, primero tenemos que ver cómo las aplicaciones
se crean utilizando entornos de desarrollo proporcionados por el proveedor u otra plataforma cruzada
herramientas como Cordova, y compárelas con lo que ofrece Xamarin. Podemos hacer esto mirando
En dos tipos principales de desarrolladores: un desarrollador independiente que trabaja en una aplicación en su
tiempo libre y un equipo de desarrollo corporativo que crea una aplicación para sus clientes.
Comenzaremos considerando cuáles son sus diferentes necesidades en términos de soporte de plataforma,
y luego compararemos las posibles opciones.
A nuestro desarrollador indie de ejemplo se le ocurrió la idea del milenio para un
aplicación asesina, FlappyFoo, que quieren vender a los consumidores en una tienda de aplicaciones. Nuestro examen
La gran corporación, FooCorp, quiere crear una aplicación DailyFoo para ayudar a sus clientes.
La Figura 1.1 describe las cuatro plataformas de desarrollo móvil diferentes que podría
escoge de:
▪ Aplicaciones específicas del proveedor que utilizan los entornos de desarrollo de Apple y
Google
▪ Córdoba

▪ Nativo de Xamarin usando Xamarin.iOS y Xamarin.Android


▪ Xamarin.Forms

Aplicaciones específicas del proveedor Aplicaciones Cordova Aplicaciones Xamarin Aplicaciones de Xamarin.Forms

iOS Androide iOS Androide iOS Androide iOS Androide

Solicitud C objetivo Java Proporcionado por Proporcionado por


C# C# C# C#
capa Rápido Kotlin marco de referencia marco de referencia

C objetivo Java
Capa de interfaz de usuario C# C#
Rápido Kotlin

HTML / CSS / JavaScript C#

Negocio C objetivo Java


C#
capa lógica Rápido Kotlin

Figura 1.1 Una comparación de las diferentes plataformas de desarrollo móvil

Página 35
Presentamos las aplicaciones móviles de Xamarin 55

Este diagrama muestra los lenguajes de programación utilizados y dónde se puede compartir el código.
para cada capa de la aplicación, desde la capa de la aplicación (el envoltorio delgado alrededor del
resto de la aplicación que lo convierte en algo que se puede ejecutar en cada plataforma), abajo
a través de la capa de IU a la capa de lógica de negocios. Las cajas no están a escala, son
solo una representación de las capas. Tu aplicación podría tener mucha IU pero poca lógica, así que
la capa de IU sería más grande o viceversa. Veamos cada uno de estos con más detalle.

1.1.1 Aplicaciones nativas específicas del proveedor


Cada sistema operativo viene con un conjunto diferente de API, un paradigma diferente para construir el usuario
interfaz, una forma diferente de manejar las interacciones del usuario y, lo más frustrante, una diferencia
lenguaje de programación diferente (o elección de idiomas) para su uso. Si quieres
crear una aplicación para dispositivos basados en iOS de Apple, como iPhones y iPads, necesita
programa en Objective-C o Swift. Para teléfonos y tabletas Android, debe
programa en Java (con soporte de Kotlin próximamente).

https://translate.googleusercontent.com/translate_f 22/131
23/2/2020 Jim Bennett
Para cada plataforma, terminarás creando la aplicación completa desde la interfaz de usuario
capa hasta cualquier lógica de negocios en la aplicación, todo en el idioma preferido del proveedor, como
se muestra en la figura 1.2.

iOS Androide

Solicitud C objetivo Java


capa Rápido Kotlin

C objetivo Java
Capa de interfaz de usuario
Rápido Kotlin

Negocio C objetivo Java


capa lógica Rápido Kotlin Figura 1.2 Uso de aplicaciones específicas del proveedor
el mismo lenguaje para todas las capas pero
diferentes idiomas en cada plataforma

Para nuestro desarrollador independiente, este es un gran problema. Para que FlappyFoo sea un éxito, será
necesita un alcance máximo, y esto significa tanto las versiones de iOS como de Android. Conseguir
esto, el desarrollador independiente tendrá que aprender dos lenguajes de programación, y hay
hay más que aprender que la sintaxis del lenguaje: tendrán que aprender diferentes herramientas, diferentes
diferentes formas de obtener acceso a código de terceros, las diferentes palabras que los desarrolladores usan para
expresa cada concepto y los diferentes patrones de diseño que componen las aplicaciones estándar.
Esta es una gran tarea.
Incluso si el desarrollador independiente es un políglota y está contento en múltiples entornos,
Todavía queda la cuestión del tiempo. Tendrán que codificar la misma aplicación dos veces, implementando
La misma lógica en diferentes idiomas. El tiempo de comercialización es clave, y si el desarrollador golpea
solo una plataforma para comenzar, no hay nada que impida que los imitadores inunden
Otra plataforma rápidamente. FlappyFoo puede dominar la tienda de aplicaciones de iOS, pero podría perder seri
ous ingresos a FlappyBar de otro desarrollador en Android.

Page 36
66 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

Para nuestro equipo corporativo, el mayor problema es el costo. Para llegar a múltiples plataformas usu-
Aliado significa un equipo por plataforma con el desarrollador asociado y la organización
costos. Esto puede ser especialmente problemático si considera las dificultades para encontrar
ing, y retener buenos desarrolladores. Lo ideal es que puedas lanzar simultane-
solo en todas las plataformas, y para replicar cada nueva característica en ambas plataformas y lanzar
ellos simultáneamente Esto es difícil si ha logrado emplear cinco desarrollos de Android.
solo hay dos desarrolladores de iOS (un escenario común ya que es mucho más fácil encontrar Java
desarrolladores en el entorno corporativo para ayudar con las versiones de Android de lo que es
encontrar desarrolladores de Objective-C o Swift).
Pensando en los clientes de la corporación que usan DailyFoo todos los días para rastrear sus
Foo, lo último que queremos es que cambien de plataforma, descubran que la nueva plataforma
A la versión del formulario le falta una característica asesina de DailyFoo, y salta a MyBar desde
BarCorp.
Sin embargo, no todo es malo. De lo único que siempre puede estar seguro al escribir un
La aplicación que utiliza las herramientas proporcionadas por el proveedor es que siempre está creando una aplicación verdaderamente nativa
catión que tendrá el mayor rendimiento posible y que soporta todo lo que
El sistema operativo y los dispositivos tienen que ofrecer. Cada vez que se lanza una actualización del sistema operativo, las herramientas siempre
actualizado para que coincida, dándole acceso a todas las funciones más nuevas que sus usuarios desearán
tener. Esta es una consideración importante, ya que los usuarios de la aplicación son volubles. Ellos rápidamente
soltar una aplicación para un competidor si no está a la altura, es lenta, torpe o simplemente no está bien
integrado en su dispositivo.

1.1.2 Córdoba
Como ya se mencionó, usar múltiples idiomas iOS Androide

y las herramientas de desarrollo son un dolor de cabeza. Una popu-Solicitud Proporcionado por Proporcionado por
Una forma de evitar esto es usar Cordova. Este es un conjunto capa marco de referencia marco de referencia

de herramientas que le permiten crear aplicaciones web


Capa de interfaz de usuario
usando HTML, JavaScript y CSS para construir un
sitio web móvil, que luego se envuelve en una aplicación
y empaquetado para cada plataforma, como se muestra en HTML / CSS / JavaScript

Negocio
figura 1.3. capa lógica
Esto tiene la gran ventaja de un lenguaje común.
Indicador y entorno de desarrollo: una herramienta
configurado para que el desarrollador independiente aprenda, o unFigura
equipo
1.3 Aplicaciones de Cordova:
en un entorno corporativo Los inconvenientes HTML / CSS / JavaScript para la interfaz de usuario y
lógica de negocios envuelta en una aplicación por
sin embargo, puede superar seriamente esta ventaja. Primero,
El marco de Córdoba.
no estás creando una aplicación nativa, estás creando
Una aplicación web. Esto significa que los widgets que ves en
La interfaz de usuario son widgets HTML diseñados para parecerse a componentes nativos. Esto podría
engaña a tus usuarios ahora, pero si una actualización del sistema operativo cambia el estilo, tus aplicaciones no seguirán el ritmo
sin una reconstrucción y se verá desactualizado. En segundo lugar, el SO y las características específicas del dispositivo.
que están disponibles para el desarrollador nativo no estarán disponibles para un desarrollador de Cordova.

https://translate.googleusercontent.com/translate_f 23/131
23/2/2020 Jim Bennett

Page 37
Presentamos las aplicaciones móviles de Xamarin 77

Las herramientas hacen todo lo posible para proporcionar algunos complementos de mínimo común denominador para
permitir el acceso al hardware y al sistema operativo, pero estos están escritos con el objetivo de ser cruzados
plataforma, por lo que solo admiten las características comunes a ambas plataformas. También son
Más tarde al mercado. Si el proveedor lanza una nueva característica que desea aprovechar,
tendrá que esperar a que se cree el complemento Cordova para admitirlo, y esto puede
nunca suceda
Pensando en nuestro desarrollador independiente, si usan Cordova para construir FlappyFoo, podría
ejecutar fácilmente lentamente, especialmente en dispositivos más antiguos. Esto puede conducir a una franja de una estrella
revisiones, falta de ventas y el desarrollador pasa hambre. Las aplicaciones de Cordova también se ejecutan en un
navegador, por lo que están limitados por la velocidad y el conjunto de características de ese navegador, verso más reciente
Las versiones del sistema operativo pueden tener un navegador rápido con todas las funciones, pero las versiones anteriores pueden ser
carente. Esto puede conducir a diferentes capacidades o diferentes niveles de rendimiento en
el mismo dispositivo pero con diferentes versiones de sistema operativo, algo que es muy difícil de probar
El ecosistema enormemente fragmentado de Android.
Para nuestro equipo de desarrollo corporativo que crea DailyFoo, una aplicación lenta o que
se ve desactualizado una vez que sale una actualización del sistema operativo puede crear una imagen negativa del
Marca FooCorp. Si la aplicación MyBar del rival BarCorp admite 3D touch en iOS,
y DailyFoo no lo hace debido a la falta de soporte de los complementos de Cordova, nuestro voluble cliente
los tomers podrían fácilmente verse tentados a cambiar.

1.1.3 Aplicaciones nativas de Xamarin


En mi opinión, Xamarin es el claro ganador porque iOS Androide

combina lo mejor de ambos métodos anteriores. Solicitud C# C#


Fundamentalmente, Xamarin proporciona un conjunto de .NET capa

envoltorios alrededor de las API de SO nativas basadas en


Capa de interfaz de usuario
C# C#
Mono: la implementación multiplataforma de .NET
que surgió de Ximian. Esto proporciona un .NET
framework para Android e iOS, con bibliotecas y
Negocio
Un compilador de C # para cada plataforma. Significa que puedes capa lógica
C#

escribir aplicaciones en C # que se dirigen a cada plataforma móvil


de forma nativa, y porque estás usando un solo programa,
ming language, puedes abstraer fácilmente todos tus Figura 1.4 Las aplicaciones de Xamarin están escritas
en C #, para que pueda compartir común
lógica empresarial (todo lo que no interactúa con
lógica de negocios y también tienen
el dispositivo directamente) en un conjunto de bibliotecas que pueden ser
IU específicas de plataforma.
compartido entre plataformas. Incluso puedes abstraer
gran parte de la lógica de la interfaz de usuario mediante el uso de patrones de diseño
como MVVM (modelo-vista-modelo de vista, del cual aprenderá con más detalle en el capítulo-
ter 2). La figura 1.13 muestra el código dividido y compartido entre cada capa.
Echemos un vistazo más de cerca a esos últimos puntos, ya que esto es importante y es la clave
hijo en mi mente por usar Xamarin:
▪ Xamarin proporciona contenedores alrededor de las API nativas .
▪ Xamarin proporciona un compilador para cada plataforma para producir código nativo.

38
8 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

Esta es la clave. Las API nativas están envueltas en código C # para que pueda llamarlas desde su C #
código. Escribes tus aplicaciones usando los mismos modismos y clases que el código nativo puro, pero
usando C #. En iOS tienes una clase UIViewController para cada pantalla, pero este es un C #
clase, no el Objective-C del iOS SDK contra el que codifica. En Android,
cada pantalla se deriva de una clase llamada Actividad , pero es una clase C # que envuelve el
Clase de actividad Java del SDK de Android.
El código que escribe también es código compilado, esto no se encuentra dentro de alguna emulación.
tor en el dispositivo; está compilado en código nativo que interactúa con las mismas bibliotecas que
una aplicación escrita en el idioma de elección del proveedor y compilada con sus herramientas. Esta
significa que tu aplicación es verdaderamente nativa. Utiliza widgets nativos en la interfaz de usuario, tiene acceso a cada
dispositivo y sistema operativo a los que la API nativa tiene acceso, y es tan rápido como una aplicación nativa.

APLICACIONES XAMARIN == APLICACIONES NATIVAS Esta es la característica asesina de las aplicaciones Xamarin.
Están escritos en C # y tienen acceso a todas las funciones de ese lenguaje,
a una gran parte del marco .NET al que los desarrolladores de escritorio están acostumbrados,
y a una gran cantidad de código de terceros. Pero el resultado final es el código nativo: el
igual que el creado en Objective-C o Swift en iOS, o Java en Android.

En iOS, el compilador de C # toma su código y produce un binario nativo de iOS usando un


Compilador anticipado (AOT) (figura 1.5).
En Android crea código IL (igual que para las aplicaciones C # que se ejecutan en Windows),
que se compila en tiempo de ejecución utilizando la compilación just-in-time (JIT) (figura 1.6). Esto es

https://translate.googleusercontent.com/translate_f 24/131
23/2/2020 Jim Bennett
proporcionado por un tiempo de ejecución Mono integrado en su aplicación e instalado con él (pero no
te preocupes, solo obtienes los bits del tiempo de ejecución Mono que necesitas, gracias a un muy buen
enlazador). Xamarin también tiene un compilador AOT para Android, pero al momento de escribir, es
Todavía muy experimental.

¿Qué pasa con otros idiomas? También


puedes escribir tus aplicaciones usando F # si
Prefiero un estilo de programación más funcional. F # es totalmente compatible con iOS
y aplicaciones de Android. Si lo tuyo es VB.NET, puedes compilar .NET Standard
bibliotecas de clases que lo usan y llame a estos desde sus aplicaciones iOS y Android integradas
usando C # o F #. Sin embargo, esas opciones están fuera del alcance de este libro:
aquí solo nos enfocaremos en C #.

SDK de iOS
(C objetivo)

Envoltorio C # Compilador AOT


aplicación iOS
(Xamarin.iOS)

Aplicación C #
Figura 1.5 Usos de Xamarin.iOS
Un compilador anticipado.

Página 39
Presentamos las aplicaciones móviles de Xamarin 99

SDK de Android
(Java)
aplicación Android
Envoltorio C # Compilador IL (Código IL,
(Xamarin.Android) Tiempo de ejecución mono,
Compilador JIT) Figura 1.6 Xamarin Android
Aplicación C #
utiliza un compilador Just-in-time
y un tiempo de ejecución Mono.

Debido a que el lenguaje de elección es C #, las bibliotecas de códigos escritas para compartir código entre
iOS y Android también se pueden compartir con una aplicación UWP (Plataforma universal de Windows),
para que pueda orientar fácilmente dispositivos Windows 10 desde computadoras de escritorio a tabletas y teléfonos a
XBox One si así lo deseas.
Para nuestro desarrollador independiente, esta es una buena noticia. Solo tienen un idioma para aprender,
y solo tienen que escribir la mayor parte de su aplicación una vez, y luego escribir el dispositivo-
capa específica una vez por plataforma que desean admitir. Esto da un tiempo más rápido para estropear
ket, que es vital para las aplicaciones de consumo. También significa que el código lógico central se prueba
Del mismo modo en todas las plataformas, los errores se corrigen una vez, y las mejoras y las nuevas características
se crean con menos cambios.
Para nuestro equipo de desarrollo corporativo, esto también es bueno, ya que significa menos
desarrolladores y menos costo. Idealmente, habría algunos desarrolladores que se especializan en
modismos específicos de la plataforma de cada sistema operativo compatible que puede trabajar en la interfaz de usuario o dispositivo
lógica específica, pero el núcleo del equipo de desarrollo puede construir la lógica empresarial una vez
en un solo idioma También es más fácil construir los equipos de desarrollo porque C # desarrolla
los operadores son fáciles de encontrar, mucho más fáciles que los desarrolladores de Objective-C. Las ventajas para
el desarrollador independiente también se aplica aquí: menos código para probar y más rápido para comercializar con error
correcciones y nuevas características.
Esto no es una utopía total. Los desarrolladores de Xamarin todavía tienen que escribir la capa de interfaz de usuario y
todo lo que interactúa con el dispositivo usando el código C # específico de la plataforma y todavía
necesitan entender los modismos de cada plataforma, pero solo tienen un idioma para
apoyo. Una sintaxis, un conjunto de herramientas, una forma de usar código de terceros.
Es fácil ver esto y pensarlo como un fracaso parcial, algo que se pierde
la marca al no ser totalmente multiplataforma, pero ese es realmente uno de sus puntos fuertes. Por
Al tener API específicas de la plataforma C #, obtienes lo mejor de lo que el dispositivo tiene para ofrecer. Tú
no se limitan a un subconjunto común; en su lugar, puede escribir la aplicación de cada plataforma de una manera
eso aprovecha al máximo las características de esos dispositivos. También significa que tienes acceso a
todo: cuando iOS agrega una nueva función, Xamarin ajusta su API y está disponible para
más o menos el mismo día Sus aplicaciones pueden orientarse a cada plataforma, por lo que
verse y sentirse como una aplicación pura y nativa y aprovechar las características únicas que

Page 40
10 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

https://translate.googleusercontent.com/translate_f 25/131
23/2/2020 Jim Bennett

hacen que Android e iOS sean tan diferentes, pero detrás de escena estás compartiendo
75% de su código base. La tabla 1.1 muestra algunos ejemplos de este código compartido.

Tabla 1.1 La cantidad de código en dos aplicaciones populares reutilizadas entre iOS y Android

TouchDraw
iCircuit (http://icircuitapp.com)
(http://elevenworks.com/home)

iOS 70% 61%

Androide 86% 72%

Hay una desventaja en el uso de Xamarin para sus aplicaciones móviles: depende de
ellos envolviendo los SDK y asegurando que los compiladores funcionen en todas las plataformas requeridas
formas Hay una sobrecarga para envolver los SDK, y aunque Xamarin tiene
muy, muy bueno en eso, todavía puede haber una brecha entre una API disponible
Apple, Google y Xamarin lo tienen envuelto. Esto generalmente no es un problema, ya que
tanto Apple como Google lanzan versiones beta lo suficientemente temprano como para que Xamarin tenga tiempo
para hacer frente a cualquier peculiaridad.
Lo único que ha sido un problema es cuando el compilador subyacente requiere:
los cambios cambian Esto sucedió recientemente con las aplicaciones de Apple Watch: originalmente eran
código nativo compilado, pero para watchOS 2 el compilador de Apple cambió a byte de salida
código en lugar de código nativo. A Mono le tomó mucho tiempo ponerse al día y poder
compila las aplicaciones watchOS 2 de trabajo. Este es el mayor riesgo con Xamarin: que Apple
o Google podría cambiar por completo la forma en que crean aplicaciones, y para cuando Xamarin
se pone al día, su aplicación podría haber llegado tarde al mercado con una nueva característica o dispositivo
apoyo.
Ahora que Xamarin es propiedad de Microsoft, puedo ver que esto es menos problemático ya que
Tendrán más recursos para combatir este problema.

1.1.4 Xamarin.Forms
Xamarin también ofrece una solución más multiplataforma iOS Androide
llamado Xamarin.Forms que intenta traer código Solicitud C# C#
reutilice hasta el 95–98% abstrayendo la IU y capa

capas de código específicas del dispositivo. A diferencia de las aplicaciones de Cordova


Capa de interfaz de usuario
que usan HTML, Xamarin. Las aplicaciones de formularios siguen siendo nativas
aplicaciones Utiliza una abstracción que se encuentra encima de
C#
Plataformas iOS y Android y ofrece un precio más bajo
Negocio
experiencia de denominador común, proporcionando fea- capa lógica
Tures que son comunes a ambas plataformas. Haciendo
esto, puede obtener hasta un 98% de reutilización de código. Esto es
se muestra en la figura 1.7. Figura 1.7 Aplicaciones de Xamarin.Forms
Esta abstracción se realiza utilizando un conjunto de clases de IUtener una interfaz de usuario multiplataforma para compartir
Aún más código.
que representan características comunes a ambos, y cuando

Page 41
Presentamos las aplicaciones móviles de Xamarin 11

la aplicación se ejecuta, estos se traducen a los equivalentes nativos detrás de escena. por
Por ejemplo, cada pantalla que ve es una página , y esta se representa en iOS usando un UIView-
Controlador y en Android usando una Actividad . Si agrega un botón a esta página, es un
UIButton en iOS y un widget de botón en Android. A diferencia de Córdoba, que utiliza
HTML para proporcionar la capacidad multiplataforma, Xamarin.Forms utiliza el real, nativo
controles, para que tengas una verdadera experiencia nativa. Si el sistema operativo actualiza el aspecto del botón-
toneladas, sus aplicaciones de formularios se verán como la nueva versión. Esta abstracción está expuesta no
solo como un conjunto de clases de C # que puede usar desde su código de C #, pero también puede definir su
Interfaz de usuario con XAML: una variante de XML originalmente definida por Microsoft para crear interfaces de usuario.
XAML le permite definir su interfaz de usuario utilizando una sintaxis más declarativa, similar en
naturaleza para HTML, y es muy familiar para los desarrolladores desde un escritorio de Windows
suelo que están acostumbrados a crear aplicaciones con WPF. Si ha creado WPF o Windows 10
aplicaciones, probablemente habrás encontrado XAML antes. Xamarin.Forms utiliza un poco
variante diferente de XAML que WPF / Windows 10, pero la mayoría de los conceptos son los
mismo. Esta similitud aumentará con el tiempo porque Microsoft está en proceso de
definiendo XAML Standard, una única sintaxis XAML que se utilizará en todos los Micro-
herramientas XAML suaves.
La desventaja es que está creando una aplicación para todas las plataformas. Aunque trata de
ser lo más nativo posible mediante el uso de controles nativos, no puede moverse fácilmente por la plataforma
modismos específicos. Por ejemplo, si tiene una aplicación que tiene dos pantallas para trabajar,
navegarías en Android usando un cajón expuesto por un menú de hamburguesas, mientras que en
iOS usarías pestañas. Esta diferencia no es fácil de implementar en formularios sin una gran cantidad de
lógica personalizada y UI personalizadas. Si quieres ir más allá del mínimo común
denominador (por ejemplo, agregar un comportamiento específico de la plataforma a un control en uno
plataforma), entonces necesitaría escribir un renderizador personalizado para él: código que se asigna desde
Forma controles al control subyacente.
Los formularios intentan abstraer las características específicas del dispositivo, como los mapas o la cámara
usando complementos, pero nuevamente es un modelo de mínimo común denominador. La Cámara

https://translate.googleusercontent.com/translate_f 26/131
23/2/2020 Jim Bennett
el complemento no te dará fotos en vivo en iOS, y el complemento de mapas no te da el
la misma cantidad de control que Google Maps en Android.
Para nuestro desarrollador independiente, los formularios pueden no ser la mejor opción: la cantidad de trabajo
se necesitaría para que una aplicación se vea y se sienta como si una verdadera experiencia nativa pudiera salir-
sopesar el ahorro de tiempo al maximizar la reutilización del código.
Para los desarrolladores corporativos, podría ser una mejor opción. Ciertamente para aplicaciones internas,
donde no siempre necesitas una experiencia nativa asesina, es una gran herramienta, pero para
Es posible que no proporcione todas las funciones necesarias. Estoy seguro de que con el tiempo lo hará
seguir mejorando cada vez más, está bajo un fuerte desarrollo en este momento, pero
Todavía no está allí para una gran aplicación de consumo.
Este libro se centra en las aplicaciones móviles nativas de Xamarin, pero en los principios de MVVM
que cubriremos también se aplican a las aplicaciones Xamarin.Forms.

Page 42
12 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

1.1.5 Herramientas para desarrolladores de Xamarin


Como he demostrado, Xamarin es, de lejos, la mejor opción para el desarrollo móvil:
le brinda el poder y el rendimiento de una aplicación nativa, brindándole acceso a todo
en los SDK y en los dispositivos, y usa C # como lenguaje común en todas las plataformas
para que pueda compartir la mayoría de su código base. Entonces, ¿cómo haces para construir un
Aplicación Xamarin?
Para las aplicaciones nativas puras, los proveedores proporcionan herramientas: las aplicaciones iOS se crean utilizando
Xcode en la Mac y las aplicaciones de Android se crean con Android Studio en Mac / Win-
dows / Linux.
Para las aplicaciones de Xamarin, el mejor IDE es el Visual Studio de 20 años de Microsoft. Eso
viene con una cantidad ridícula de características y herramientas, y tiene una amplia gama de
extensiones para proporcionar todo tipo de nuevas características. Está disponible como una edición comunitaria.
para desarrolladores independientes y pequeños equipos de forma gratuita, y se escalona a partir de ahí dependiendo de
qué tan grande es su equipo, cuáles son sus necesidades de soporte y si desea una empresa
características como perfiladores o ensamblajes de incrustación (puede comparar los diferentes niveles
en www.visualstudio.com/vs/compare/ ). Xamarin está completamente integrado en Visual Studio, pro
ofreciendo una experiencia totalmente nativa en la que puede crear una nueva aplicación dirigida a iOS o
Android tan fácilmente como puede crear una aplicación WPF de escritorio o una biblioteca de clase. Usted puede
haga referencia fácilmente a otros proyectos, agregue paquetes NuGet y haga todo con estos
tipos de proyectos que puede hacer con cualquier proyecto nativo de Windows. Desde allí puedes
construya su aplicación de Android Xamarin y ejecútela en un emulador (Visual Studio proporciona un
número de emuladores de Android integrados) o en un dispositivo real. También puedes construir y ejecutar
una aplicación Xamarin para iOS, aunque con algunas restricciones relacionadas con Apple.
Las reglas de licencia de Apple para su SDK, compilador y herramientas de compilación requieren que usted cree
en una Mac Viendo que nuestras aplicaciones Xamarin envuelven los SDK y compilan en código nativo
usando la cadena de herramientas de Apple, debes tener una Mac. Afortunadamente Xamarin iOS en Windows
elimina el dolor de esto y proporciona soporte dentro de Visual Studio en Windows para
compilar y depurar aplicaciones iOS usando una Mac remota; todo lo que necesita es una Mac con
Xamarin instaló con el que puede conectarse, y la magia simplemente sucede. Estudio visual
se conecta a la Mac para compilar su código. El SDK de iOS en Mac incluye un
Simulador de iPhone / iPad, que puede usar para probar su aplicación, y un depurador que permite
Debes depurar aplicaciones que se ejecutan en un dispositivo conectado por USB a tu Mac, así que inicialmente
aún tenía que probar sus aplicaciones ejecutando el simulador en la Mac o usando un dispositivo
enchufado Pero Xamarin ahora también tiene eso cubierto, al menos para los simuladores. Eso
puede compartir la pantalla del simulador en su cuadro de Windows para que pueda depurar en un
simulador como si estuviera disponible en Windows. Esto significa la Mac que necesitas para construir
No es necesario que esté a su lado, o incluso en la misma red. Hay servicios en la nube
que puede alquilarle tiempo en Mac, como Mac In Cloud ( www.macincloud.com ). Usted puede
utilícelos para crear sus aplicaciones, y puede probar estas aplicaciones depurando
Visual Studio en un simulador que comparte la pantalla de nuevo a su cuadro de Windows. Figura 1.8
muestra una visión general de este proceso. Solo necesita acceso a una Mac física si desea
prueba en un dispositivo real.

Page 43
Presentamos las aplicaciones móviles de Xamarin 13

La pantalla del simulador es


compartido con PC con Windows

Simulador
se ejecuta en Mac

https://translate.googleusercontent.com/translate_f 27/131
23/2/2020 Jim Bennett

PC con Windows Código enviado a Mac para construir Mac


corriendo con Xamarin
Estudio visual Resultados de compilación enviados instalado
volver a Visual Studio

Figura 1.8 Visual Studio puede conectarse a una Mac localmente o en la nube
para construir y depurar aplicaciones de iOS en un simulador.

Hasta ahora, muy bien. Estamos creando aplicaciones móviles multiplataforma en Windows. Pero uno de los
principios fundadores del proyecto Mono que inspiraron a Xamarin que conocemos y amamos
es poder ejecutarse en diferentes plataformas, y Xamarin lo tiene cubierto allí. Visual
Studio ahora está disponible en Mac, aunque en una versión reducida en comparación con Visual
Studio en Windows. Xamarin solía tener un IDE llamado Xamarin Studio, y esto
se convirtió en la base de Visual Studio para Mac. Visual Studio para Mac admite la construcción
Aplicaciones iOS y Android, así como aplicaciones macOS, aplicaciones tvOS y sitios web ASP.NET Core.
Tiene integración de Azure que le permite construir los componentes móviles y web
de su ecosistema de aplicaciones, e incluso para depurar componentes móviles y web dentro
la misma sesión de depuración Visual Studio en Mac tiene la misma licencia que para
Windows, por lo que es gratis para desarrolladores independientes y pequeños equipos, con planes de pago disponibles
Para equipos más grandes.
La herramienta que utilices realmente depende de las preferencias personales y de las plataformas que utilices.
quiero apoyar. En este libro cubriremos Visual Studio en Windows y
Mac.

¡PLATAFORMA TRANSVERSAL TODAS LAS COSAS! Otra cosa increíble a tener en cuenta es que
Microsoft ha cambiado recientemente de una compañía cerrada que era Windows
solo para uno que admita código abierto y múltiples plataformas. Incluso han
partes de código abierto de .NET Framework y el compilador y han hecho
Es multiplataforma. Esto significa que los bits de Mono se reemplazan lentamente con
las implementaciones de Microsoft desde su marco .NET. También significa
que el compilador en Visual Studio es el mismo en Windows que en Mac, con
ambos usando el compilador de código abierto Roslyn. Cuando compilas en la Mac,
Es el mismo compilador que en Windows.

1.1.6 Ciclo de vida de desarrollo optimizado para dispositivos móviles


Hasta ahora hemos cubierto las aplicaciones de Xamarin y, para mucha gente, esto es lo que Xamarin es: un
.NET framework y compilador para iOS y Android basado en Mono. Pero tan bien como

Page 44
14 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

Al proporcionar las herramientas para crear aplicaciones multiplataforma, Xamarin también proporciona las herramientas
necesitas hacer mucho más que solo escribir el código.
Uno de los conceptos más importantes en el mundo del desarrollo en los últimos años es DevOps:
El cambio cultural a un modelo donde se combinan el desarrollo y las operaciones. Algunos
Entre los objetivos de DevOps se incluyen permitir que las personas participen en todas las partes del
ciclo de desarrollo y lanzamiento, automatizando tanto como sea posible y moviéndose a un
modelo de entrega continua donde el código se puede registrar, construir y probar automáticamente
y enviado a producción con un mínimo aporte humano. DevOps es un tema masivo, bueno
fuera del alcance de este libro, pero hay una serie de herramientas, ya sea proporcionadas por
Xamarin o bien integrado con otras herramientas de Xamarin, que pueden usarse para ayudar a implementar
Mencione una buena estrategia de DevOps.
Durante la conferencia Xamarin Evolve en abril de 2016, uno de los temas principales de
la nota clave fue el ciclo de vida de desarrollo optimizado para dispositivos móviles (como se ilustra en la figura
1.9). Durante esta nota clave, una serie de herramientas, tanto de Xamarin como de su nuevo par-
Ent empresa Microsoft, fueron discutidos. Estaba bastante claro que este era un enfoque clave para
Xamarin como compañía, y solo ha estado creciendo con la introducción de Visual Stu-
dio App Center y el mayor impulso hacia DevOps. Esto es importante ya que con-
vea cómo crear aplicaciones móviles con calidad de producción.

Desarrollar Prueba Construir Distribuir Monitor


UITest, Estudio visual Estudio visual Estudio visual
Estudio visual
Test Cloud Centro de Aplicaciones Centro de Aplicaciones Centro de Aplicaciones

Figura 1.9 El ciclo de vida de desarrollo optimizado para dispositivos móviles es un ciclo de iteración continua de
desarrollar, probar, construir, distribuir y monitorear.

1,2 Crear aplicaciones móviles con calidad de producción


Es un largo viaje desde una idea de la parte posterior de la servilleta hasta una aplicación implementada y totalmente funcional de
calidad suficiente para ser utilizable y no obtener malas críticas. Es fácil para los desarrolladores saltar
directamente a la codificación, ya que esta es la parte que amamos, pero si quieres crear una aplicación, eso es
exitoso, debe considerar todo el ciclo de vida de desarrollo de software. No hay

https://translate.googleusercontent.com/translate_f 28/131
23/2/2020 Jim Bennett
apunte a sumergirse en el código y construir algo que no se vea bien o no funcione
bueno porque no has considerado el diseño de tu aplicación terminada. Durante la codificación
debe tener en cuenta las pruebas y el monitoreo para que codifique de una manera que
los puertos Para algo más que un prototipo, tienes que pensar en todo
ciclo de vida antes de escribir una sola línea de código. Este ciclo de vida es muy similar al
el ciclo de vida de desarrollo optimizado para dispositivos móviles se habló en Xamarin Evolve, pero agrega un
Unos pocos pasos más.

Página 45
Crear aplicaciones móviles con calidad de producción 15

En este libro crearemos una aplicación de calidad de producción, así que echemos un vistazo a las etapas
La aplicación móvil tendrá que pasar por este viaje. Veremos qué puede hacer Xamarin (o
no puedo) ayudar con.

Comenzando con un MVP


Si no te da vergüenza la primera versión de tu producto, has
lanzado demasiado tarde.
—Reid Hoffman

Es una buena práctica cuando se crea una aplicación móvil para comenzar con un MVP, un mínimo viable
producto. Esta es la versión más pequeña, simple y rápida de comercializar que puede ofrecer.
Una vez que esto esté en manos de los consumidores, puede controlar cómo se usa y ofrecer funciones
basado en lo que la gente real quiere. Mucha gente piensa que una aplicación debe tener todas las funciones,
basado en su idea de qué es un conjunto completo de características, para tener éxito, pero sus usuarios
podría saberlo mejor. Es mejor sacar una aplicación rápidamente e iterar según el mundo real
comentarios, porque es muy fácil equivocarse sobre lo que debería tener una aplicación.

Por ejemplo, Flickr comenzó como un juego de rol en línea con un intercambio de fotos.
herramienta, y solo la parte para compartir fotos ahora sobrevive. ¡Prepárate para pivotar!

1.2.1 Diseño
Diseñar una aplicación es difícil, especialmente para los desarrolladores sin capacitación formal en diseño.
Todos hemos visto algunas interfaces de usuario bastante impactantes, principalmente para aplicaciones internas donde los desarrolladores
arrojé todo el contenido y los controles a la pantalla y lo dejé así. En el
sumer mundo móvil, esto ya no es una opción. Los usuarios pueden saltar a otra aplicación
que hace lo mismo que el tuyo en el tiempo que lleva descargar unos pocos megabytes de
datos de una tienda de aplicaciones. No tienen lealtad a su aplicación, y una mala aplicación puede eliminar
Lealtad a su negocio.
Por ejemplo, si eres un banco y las personas usan tu aplicación para interactuar con sus
cuentas todos los días y la experiencia es mala, prefieren cambiar su banco que
sigue usando tu mala aplicación. Puede salirse con la suya en un entorno corporativo donde
sus usuarios son internos y tienen que usar lo que sea que pongan delante de ellos, pero estén pre
comparado con las quejas que pueden no ser buenas para el progreso de su carrera, especialmente si
El CEO es uno de los usuarios.
Hay varias cosas a tener en cuenta al diseñar una aplicación:
▪ Consistencia: su aplicación se ve y funciona como otras aplicaciones en la misma plataforma.
formulario, especialmente los proporcionados por el proveedor del sistema operativo.
Por ejemplo, las aplicaciones de Android deben seguir la pila de actividades con el botón Atrás pero-
Ton haciendo lo que esperarías. Las aplicaciones de iOS deben usar pestañas para cambiar entre popu-
Lar acciones.

Página 46
dieciséis C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

▪ Experiencia del usuario: ¿es su aplicación fácil de usar e intuitiva? Un usuario debería poder
simplemente recójalo y sepa cómo usarlo sin ningún tipo de capacitación. Ser consistente
con otras aplicaciones puede ayudar con esto.
Por ejemplo, evite los iconos personalizados para botones o elementos de menú. En cambio, use
los que son estándar de la industria o simplemente usan texto. A nadie le importa que pienses que
El uso de sus propios iconos personalizados ayudará a promocionar su marca y a hacer que una aplicación se vea
como si fuera tuyo En cambio, lo tirarán si no pueden entender cómo usarlo.
▪ Flow: ¿ fluye bien su aplicación? ¿Hay un flujo fácil para que un usuario use la aplicación?
Cuando una acción conduce naturalmente a otra, el viaje entre las acciones
debe ser breve y conciso.
Por ejemplo, si su aplicación es para tomar fotos, las opciones para editar o compartir
Una foto debe estar en la misma pantalla donde ves la foto que has
tomado, no enterrado en un menú que involucra múltiples pasos para navegar.

https://translate.googleusercontent.com/translate_f 29/131
23/2/2020 Jim Bennett
▪ Buena apariencia: su aplicación se ve bien, cualquier imagen bien dibujada y apropiada
comió para el tamaño del dispositivo, todo el texto es claro y legible, y los colores son consistentes
tienda de campaña y apropiado?
Por ejemplo, una aplicación podría ejecutarse en un teléfono pequeño, teléfono grande, "phablet"
tableta pequeña o tableta grande. Cualquier texto en la pantalla debe ser legible en todos
alfombrillas, las imágenes deben tener un tamaño que se vea bien en todos los tamaños de dispositivos y elementos en pantalla
debe espaciarse para que quede claro lo que el usuario está mirando sin la interfaz de usuario
Se mezclan entre sí debido a la falta de espacio.
▪ Accesibilidad: ¿Su aplicación es accesible para usuarios con diferentes capacidades?
Por ejemplo, si un usuario aumenta el tamaño de fuente predeterminado, ¿la aplicación aún puede utilizarse?
¿Hay alertas de audio también disponibles como alertas visuales? Algo de esto depende de
su público objetivo (por ejemplo, no hay mucho que pueda hacer para crear un
reproductor de música accesible para una persona sorda), pero una aplicación bien diseñada considerará
Todos los usuarios posibles.

Puede parecer extraño introducir el diseño ahora, al comienzo del libro, pero es una cuestión importante.
Una cosa para pensar cuando construyes tu aplicación. Aunque Xamarin te proporciona
con las herramientas que necesita para escribir aplicaciones multiplataforma que compartan su código central, todavía
tiene que construir la capa específica de la plataforma, que incluye diferentes códigos de interfaz de usuario para iOS y
Androide. Como parte de esta capa de interfaz de usuario, debe considerar qué hace que cada plataforma sea diferente.
ferent y diseñe cada interfaz de usuario en consecuencia. Para que su aplicación sea un éxito, debe ser
intuitivo y se ve bien en cada plataforma, y parte de esto es la coherencia con lo que
los usuarios de cada plataforma están acostumbrados. No puedo enfatizar demasiado la consistencia de la palabra
suficiente: su aplicación no solo debe ser coherente con la plataforma, sino consigo misma. Ninguna
La diferencia causará confusión al usuario, lo que conducirá a una mala experiencia.
Idealmente, necesitas habilidad como diseñador o acceder a alguien con esa habilidad. Esta
puede ser fácil en un entorno corporativo, pero quizás no sea tan fácil para un desarrollador independiente
haciendo todo por su cuenta. Sin embargo, la buena noticia es que los diferentes sistemas operativos ven-
dors te tiene cubierto. Todos han publicado un conjunto de pautas sobre cómo construir aplicaciones
que no solo se ven y funcionan bien, sino que también son consistentes con otras aplicaciones

Page 47
Crear aplicaciones móviles con calidad de producción 17

plataforma. Google tiene diseño de materiales, Apple tiene sus pautas de interfaz humana.
Volveremos a esto más adelante en este libro cuando veamos la construcción de interfaces de usuario.
U SABILIDAD
Una de las cosas clave sobre el diseño es la facilidad de uso de su aplicación. Una aplicación que se ve pulida
pero es imposible de usar, probablemente sea peor que una aplicación que es mala de ver pero funciona
bien. Cuando diseñe su aplicación, las pautas relevantes de la plataforma pueden ayudarlo
asegura cierta coherencia con otras aplicaciones, pero aún así eres responsable de garantizar un
Gran experiencia de usuario. Mientras piensa en el diseño, también pruebe su experiencia de usuario
virtualmente, ya sea con herramientas en línea (de las cuales hay muchas) o herramientas simples como
prototipos de papel. Con estos puedes simular la interfaz de usuario y cómo funciona y realmente
pruébelo: haga que la gente use la versión virtual o en papel como si fuera una aplicación real y vea si
Es natural para ellos. Si ven la primera pantalla de su aplicación y no tienen idea de qué
entonces podrías perder un cliente. A veces solo tienes segundos para atraer a un usuario
antes de que decidan que su aplicación no es buena y la eliminan, por lo que es vital hacer las primeras
interacciones de usuario simples y obvias. Un libro muy popular sobre la experiencia del usuario.
El diseño resume el principio más importante en su título: "¡No me hagas pensar!" .

1.2.2 Desarrollar
Esta es la parte divertida: la parte que más amamos como desarrolladores. A pesar de ser el mejor
poco, también puede ser menos divertido si no tenemos buenas herramientas para ayudar. Un buen desarrollador puede
código en un editor de texto sin formato, pero es doloroso cuando estás acostumbrado a un IDE con todas las funciones.
Afortunadamente, como desarrolladores de Xamarin, estamos mimados. En Windows hay Visual Studio,
que es en mi opinión el mejor IDE, especialmente cuando se combina con extensiones
como ReSharper de JetBrains. En Mac hay Visual Studio para Mac, que usa el
misma plataforma de compilación que Visual Studio en Windows. Estos IDEs le dan código de comp
pletion, refactorizaciones fáciles de usar e indicaciones en el editor de sospechas o errores
código. También proporcionan soporte completo de depuración para aplicaciones Xamarin que se ejecutan en
un emulador / simulador o en un dispositivo real.
Como todas las aplicaciones de Xamarin son aplicaciones .NET que utilizan un marco .NET específico de la plataforma,
funciona, tiene acceso a una gran cantidad de bibliotecas creadas por desarrolladores externos que
también están construidos en el marco .NET. A pesar de las diferencias entre .NET en Win-
dows, iOS y Android, hay un subconjunto central que es común a todas las plataformas, por lo que
las bibliotecas que se dirigen a este subconjunto se pueden usar en todas sus aplicaciones y en cualquier biblioteca que se dirija
obtener una plataforma particular se puede usar contra esa plataforma. Esto le da acceso a un
gran cantidad de código que hace todo tipo de cosas, desde conectarse a bases de datos, manejar
JSON, y la construcción de pruebas unitarias para proporcionar marcos para el desarrollo de aplicaciones
ment. El acceso a estos es proporcionado por una herramienta de empaque llamada NuGet (pronunciado New-
Obtener): estas bibliotecas se empaquetan en un archivo zip con varias bibliotecas separadas por
cualquier plataforma a la que apunten. Al momento de escribir, hay casi 57,000 únicos
paquetes disponibles en NuGet.org, y las herramientas para usar estos paquetes están integradas
Estudio visual. Simplemente haga clic derecho, seleccione Administrar paquetes NuGet y desde allí
Instala lo que necesites. Los veremos un poco más tarde porque se usarán

https://translate.googleusercontent.com/translate_f 30/131
23/2/2020 Jim Bennett
en las aplicaciones creadas a lo largo de este libro.

48
18 años C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

Las pruebas son una parte importante de la codificación: todos los buenos codificadores escribirán pruebas unitarias a medida que
código, si no antes. Afortunadamente, Visual Studio en Windows y Mac ayuda en este esfuerzo,
proporcionando una forma de ejecutar o depurar pruebas. Con pruebas de unidades en vivo en Visual Studio en Win-
dows, o extensiones como ReSharper con dotCover o NCrunch, incluso puedes ver en
el editor qué líneas de código están cubiertas por las pruebas, codificadas por colores para indicar qué pruebas
pasar y cuáles fallan, y con las pruebas ejecutándose continuamente para que se mueva de rojo a
verde mientras escribes el código. También puede obtener extensiones IDE para usar cosas como el comportamiento
diseño impulsado (BDD), que le permite escribir sus pruebas en lenguaje natural.
Cuando codifica su aplicación, debe pensar en probar todo el tiempo, hasta el punto
de elegir patrones de diseño que ayuden a mantener su código lo suficientemente separado como para que pueda ser
probado fácilmente y a fondo. Cuando veamos cómo construir realmente una aplicación más adelante en este
libro, usaremos MVVM, un patrón de diseño que permite esto, y pensaremos en
probando en cada paso.
Todas estas herramientas hacen que la codificación sea muy divertida y reducen el trabajo pesado al hacerlo
fácil de automatizar escribir código repetitivo y fácil de refactorizar, para que nunca pelees
con tu código para mejorarlo.

1.2.3 Prueba
Las pruebas realmente van de la mano con la codificación. Es algo que debería ser continuo.
Ous, e idealmente automatizado. Probar cada función de su aplicación lleva mucho tiempo, y
a veces es muy difícil probar cada escenario, incluidos los casos extremos. Si puedes
automatice esto, no solo ahorra tiempo sino que significa que puede probar completamente su aplicación en
Cada etapa de desarrollo. De esa manera puedes atrapar errores tan pronto como aparezcan, así que
sabes qué cambios los introdujeron y puedes arreglarlos mientras estos cambios
son frescas en tu mente Si no los conoce hasta el final del desarrollo, es
es mucho más difícil determinar qué causó el error y encontrar una solución.
La capacidad de ejecutar pruebas unitarias dentro de su IDE es algo bueno porque tiene que
piensa en cómo probar tu código mientras escribes. Hay tres tipos de pruebas para
piense en: pruebas unitarias, pruebas de IU y pruebas manuales.
PRUEBA DE U NIT
Las pruebas unitarias son unidades de código de prueba, siendo una unidad el aislante más pequeño posible
pieza de código Estas son pruebas de caja negra contra el contrato de una clase, diseñadas para probar
esa clase en aislamiento. Si esa clase tiene dependencias de otras clases, esas dependencias
Las burlas deben ser burladas y tener un comportamiento predefinido para asegurarse de que solo está probando
ing la clase única en aislamiento.
Por ejemplo, supongamos que tiene una clase Counter que tiene una propiedad Count y un
Método IncrementCount . El comportamiento de la clase es que cuando llamas Incremento-
Count , el valor Count aumenta en 1. Aquí puede escribir una prueba que crea la clase,
llama a IncrementCount y verifica que Count ha aumentado en 1 y solo en 1. Si
no sube, la prueba falla; Si sube por otra cosa que no sea 1, la prueba falla. Tú
no me importa la implementación de la clase: no importa cómo se incrementa,
ya que esto podría cambiar en cualquier momento. Solo te importa el contrato, ese Incremento
El recuento incrementa el recuento en 1. Una vez que se escribe esta prueba, puede estar seguro de que este método

Página 49
Crear aplicaciones móviles con calidad de producción 19

funciona, y si aparece un error en su aplicación que parece que Count se incrementa en 2,


puede ver fácilmente que si la prueba de unidad pasa, el error está en otra parte de su aplicación.
Otro ejemplo sería un método SaveCount en su clase Counter que guarda
el recuento a un servidor web haciendo una llamada REST que pasa un poco de JSON. Si tu clase es
bien escrito, no debería hablar directamente con el servidor web, sino resumirlo a otro
clase (lo llamaremos WebService ) que realmente hace la llamada. Tu clase solo necesita
construya el JSON y dígale a la otra clase qué punto final REST usar, pasándole el
JSON En este caso, cuando construye su instancia de clase Counter , debe pasarla
la instancia de WebService para que tenga algo a lo que llamar. Como es, esto no está bien separado en
una unidad para probar, pero podemos cambiar eso.

Mostrador

IWebService

Figura 1.10 Burlarse es un simple


técnica que le permite realizar pruebas unitarias
MockWebService Servicio web
sin preocuparse por las dependencias.
Prueba de unidad Aplicación de producción

https://translate.googleusercontent.com/translate_f 31/131
23/2/2020 Jim Bennett

Si la clase WebService implementa una interfaz, IWebService , que define el


método para hacer la llamada al servidor, en su lugar puede pasar la interfaz cuando
estructura tu contador . Al hacer esto, puede burlarse de la interfaz en su prueba unitaria, eso
es decir, tener dentro de la prueba otro objeto que implemente la interfaz que tiene
control de. De esta manera, puede llamar al método SaveCount y luego inspeccionar la llamada
que se realizó en su interfaz y verifique que se llamó al punto final correcto con
El JSON correcto.
PRUEBAS DE UI
Las pruebas de IU son completamente opuestas a las pruebas unitarias. Aquí estás considerando tu aplicación
en su conjunto y probándolo como si fuera un usuario real interactuando con la aplicación. Xamarin
proporciona una herramienta llamada UITest para habilitar esto. Es una biblioteca que te permite escribir pruebas
que parecen pruebas unitarias y que se ejecutan usando NUnit (una herramienta popular de prueba unitaria), pero
Estas pruebas iniciarán su aplicación en un emulador / simulador o dispositivo físico y
formar interacciones como tocar o deslizar y le permiten consultar la interfaz de usuario para verificar que
Todo funciona como se esperaba.
Por ejemplo, en una aplicación que tiene un recuento que se muestra en una etiqueta y un botón que toca
para aumentar el recuento, puede escribir una prueba de IU que inicie la aplicación, lea el
valor de la etiqueta de conteo, toca el botón, luego vuelve a leer la etiqueta, asegurándose de que
El valor ha aumentado. Xamarin UITest hace esto al encontrar elementos dentro del árbol visual
(la representación de la interfaz de usuario en la pantalla) en función de su nombre, ID o contenido. Una vez
encuentra estos, puede leer datos o realizar acciones como tocar, por lo que una prueba podría encontrar el

Página 50
20 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

etiqueta de recuento basada en que tiene una ID de recuento definida dentro del diseño de Android o
Storyboard de iOS, y podría leer la propiedad de texto desde allí. Las pruebas de IU también pueden llamar
puertas traseras: estos son métodos especiales integrados en su aplicación para permitirle realizar
prueba más fácilmente. Puede usarlos para hacer cosas como rellenar previamente datos para evitar
formando muchos pasos repetitivos en la interfaz de usuario, o para emular situaciones que son difíciles de hacer
a través de una prueba de IU, como apagar WiFi en Android para probar problemas de conectividad.
Una vez que tenga pruebas de IU que se ejecutan y pasan un emulador o su dispositivo físico, se
Sería bueno ejecutarlos en más dispositivos. Una de las desventajas del desarrollo móvil
ment es la gran cantidad de dispositivos posibles y versiones del sistema operativo. En iOS esto no es así
un problema porque la mayoría de las personas mantienen su sistema operativo actualizado, y solo hay un pequeño rango
de dispositivos. En Android es un problema enorme ya que hay miles de posibles
dispositivos y las actualizaciones del sistema operativo no están disponibles para todos debido al fabricante y al operador
ajustes proporcionados Si Google actualiza Android, el fabricante del dispositivo debe tomar
esa actualización y aplicarla a su versión de Android y dársela al operador, quien luego
necesita aplicarlo a su versión antes de que esté disponible para instalarse en el dispositivo. en un
En muchos casos, el fabricante o el operador no lo harán, especialmente para dispositivos más antiguos,
lo que significa que hay una fragmentación masiva de las versiones del sistema operativo en Android. En el momento de
En la escritura, el 85% de los dispositivos iOS tienen la última versión de iOS. En Android, solo el 7.5%
están a la última, con 20% de una versión detrás, 16% de dos versiones detrás, 33% de tres
versiones anteriores, y el resto en versiones anteriores.
Lo que Xamarin proporciona para evitar esto es un servicio llamado Test Cloud. Esto es
miles de dispositivos físicos de diferentes fabricantes con diferentes versiones de SO
configurar en un centro de datos, y puede alquilar tiempo en estos dispositivos para ejecutar sus pruebas de IU.
De esta manera, puede cubrir una amplia gama de tamaños de dispositivos y versiones de sistema operativo, y cuando
revise los resultados que ve no solo qué pruebas pasan o no, sino que puede obtener capturas de pantalla
de cada paso, para que pueda ver cómo se ve la interfaz de usuario. Esto puede ser invaluable cuando tienes un
error que solo se manifiesta en un sistema operativo o un tamaño de pantalla y no tienes un
emulador o dispositivo físico disponible que lo replica. Esto está integrado en Visual
Studio: un clic para implementar su prueba y ejecutarla en la nube.

PRUEBAS M ANUALES
Sí, estás solo con este. La prueba manual significa que tienes que interactuar con
su aplicación para probar todo. Idealmente, si ha implementado buenas pruebas de unidad y UI,
has verificado que tu aplicación funciona correctamente. Las pruebas manuales deberían ser rápidas.
Verificación de la cordura para garantizar cualquier caso límite que no pueda probarse utilizando la automatización (como
iniciar aplicaciones externas) están funcionando. También debe probar manualmente a medida que avanza,
para verificar la usabilidad de la aplicación, verificando la experiencia del usuario. Las pruebas automatizadas pueden
verificar si algo funciona correctamente, pero aún necesita interactuar con la aplicación
usted mismo para ver si las cosas funcionan intuitivamente. Después de implementar cada función en la aplicación,
deberías probarlo para asegurarte de que sigue el diseño de tu aplicación (así como el diseño
directrices para cada aplicación), y para garantizar que sea fácil de usar y brinde buenos comentarios.
Para las pruebas de usabilidad, también debe considerar las pruebas de pasillo, acercarse a las personas
y hacer que prueben la aplicación y vean qué comentarios dan. Cuando tu lo hagas

www.allitebooks.com

51

https://translate.googleusercontent.com/translate_f 32/131
23/2/2020 Jim Bennett
Crear aplicaciones móviles con calidad de producción 21

esto, debes tratar de imitar la experiencia del mundo real tanto como sea posible. Solo da
les deja la aplicación y la dejan sin ayuda, al igual que un usuario final que acaba de
Lo descargué de la tienda de aplicaciones. Si no pueden resolver cómo usar su aplicación, puede
Necesito reconsiderar la experiencia del usuario.

1.2.4 Construir
La integración continua (CI) es el proceso mediante el cual integra continuamente su
el código cambia a la base de código central y lo prueba cada vez. En su forma más simple, es
tener algo que detecta cuando el código se cambia dentro de su repositorio de código fuente
tory (como en GitHub o BitBucket), crea su aplicación y ejecuta sus pruebas para que pueda
vea inmediatamente si ha roto la compilación o introducido un error. Este es un gran tema, así que
No lo cubriré con mucho detalle aquí, pero tocaré algunas áreas que son relevantes para
Desarrolladores de Xamarin. Hay varias herramientas de CI diferentes, y todas
tiene cierto grado de soporte para las aplicaciones de Xamarin (incluso las más básicas son compatibles
Xamarin, porque las herramientas funcionan desde la línea de comando).
Hay cientos de posibilidades para los tipos de compilaciones que podría configurar desde un
Sistema de CI. Por ejemplo, podría tener una compilación de registro que supervise su fuente
repositorio de código, y cada vez que se registra un nuevo código, lo construye y ejecuta toda su unidad
pruebas Entonces podría tener otra compilación que se ejecute a la misma hora todas las noches, obtener-
ting el último código, compilándolo, ejecutando las pruebas unitarias y luego ejecutando toda la IU
pruebas a nivel local. Finalmente, podría tener una versión de lanzamiento que se activa manualmente, que
obtiene el código, lo construye, ejecuta las pruebas unitarias, ejecuta las pruebas de IU y (si todo pasa) el paquete-
envejece la acumulación y la implementa en la tienda de aplicaciones.
Lo principal que desea con estas compilaciones es el ciclo de retroalimentación continua: cada
el check-in debe verificarse para ver si se construye y se pasan las pruebas; si hay alguno
errores, la persona que verifica el código debe ser notificada para que pueda corregir el error
directamente. Algunos sistemas de CI incluso pueden llevar esto más allá y proporcionar compilaciones previas a la confirmación:
se crea el código que desea confirmar y se ejecutan las pruebas, y solo si todo pasa es
El código comprometido. Si la compilación o las pruebas fallan, la confirmación se revierte.
Al elegir un sistema de CI, debe considerar cuán bueno es su apoyo para
Aplicaciones de Xamarin y cuánto tiempo quieres dedicar a configurarlas. Jenkins, por
ejemplo, es una herramienta gratuita y es fantástica para aplicaciones Java, pero su compatibilidad con Xamarin es nonex-
A la hora de redactar este documento, por lo que configurar compilaciones es mucho trabajo. Otras herramientas tienen Xam-
Arin soporte fuera de la caja, por lo que es fácil de configurar. El principal para las aplicaciones de Xamarin es
Centro de aplicaciones de Visual Studio.
El Centro de aplicaciones ( https://appcenter.ms ) se describe como "Control de misión para sus aplicaciones".
Puede conectarse a él utilizando una cuenta de GitHub o Microsoft, apúntelo a un repositorio de Git
en GitHub, VSTS o BitBucket, y luego es trivial configurar compilaciones. Tu eliges cual
tipo de aplicación para construir (iOS o Android), elija una rama desde la cual construir, apunte a su
solución o archivo de proyecto, elija la configuración de compilación y listo. Tú también puedes
agregue certificados de firma para permitir que sus compilaciones se ejecuten en dispositivos reales e incluso inicie su
aplicación en un dispositivo una vez que está construido como un control de cordura para asegurarse de que funciona.

Page 52
22 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

1.2.5 Distribuir
Usted diseñó su aplicación, la codificó, la probó y la creó. Ahora necesitas conseguirlo
en manos de tus usuarios. Puede enviarlo a la tienda de aplicaciones correspondiente, pero primero es
bueno ponerlo en manos de beta testers.
App Center le permite configurar usuarios alfa y beta y distribuir su aplicación
directamente a ellos. Una vez que tengan su aplicación, puede eliminar las compilaciones actualizadas a medida que arregla
errores o hacer ajustes, y cuando relancen la aplicación, se les pedirá a los usuarios que
Instalar estas actualizaciones. Esto es directo a los usuarios que desea hacer las pruebas, no es un
mercado abierto Sus usuarios solo podrán descargar su aplicación si están registrados
desgarrado, para que tenga el control completo de la distribución.

1.2.6 Monitor
Una vez que su aplicación se lanza y se utiliza, debe monitorearla. Si tus usuarios son
experimentando fallas, puede esperar una gran cantidad de reseñas de una estrella que impulsarán el potencial
nuevos usuarios de distancia. Su aplicación tendrá errores (es un hecho del desarrollo de software),
pero si puede controlarlos y solucionar los problemas lo antes posible, puede
mize el impacto. Si sabe que se han producido bloqueos, puede hacer algo
al respecto de inmediato, y eso ayudará con las descargas de su aplicación. Recuerda, tu
los clientes no presentarán informes de errores y esperarán ansiosamente una solución. Ellos solo descargarán otro
aplicación que hace lo mismo que la tuya.
Para el desarrollador de Xamarin, es fácil controlar los bloqueos con App Center. Tú
puede integrar el SDK de App Center en su aplicación tan fácilmente como instalar un paquete NuGet
edad y agregando una línea de código. Esto rastreará todos los bloqueos y cargará los rastros de la pila en
el sitio de App Center para que pueda ver rápidamente la línea de código donde sucedió, obtenerlo
arreglado, y obtener una nueva versión implementada. Esta es una herramienta invaluable, lo más rápido que pueda
arregle un bloqueo, menos posibilidades tiene de perder usuarios.
Además, App Center le permite hacer un seguimiento de usuarios y eventos para que pueda ver

https://translate.googleusercontent.com/translate_f 33/131
23/2/2020 Jim Bennett
no solo los datos demográficos de su audiencia, sino también cómo están usando su aplicación.
Nuevamente, esto puede ser importante para que su aplicación sea lo mejor posible. Si un particular
la función de su aplicación se usa regularmente, entonces es algo en lo que trabajar y
mejorar. Si nunca se usa una función, sus usuarios no la quieren o no
obvio, para que puedas quitarlo o hacerlo más fácil de descubrir. Si tu aplicación es popular en un
país particular, puede agregar soporte de idioma nativo para ese país si no es
Ahí ya. También puede rastrear la ruta que toma un usuario a través de su aplicación, y si aparece
Las características principales están ocultas detrás de muchas interacciones, puede cambiar la experiencia del usuario
para sacar a la superficie esas características más rápidamente.
Todo esto es fácil de agregar a su aplicación Xamarin: solo una línea de código por acción del usuario para
rastrea lo que están haciendo. Los datos demográficos llegan tan pronto como habilita el SDK. Si
Si captura los datos correctos y los usa correctamente, tendrá una herramienta poderosa para ayudar
dale forma a tu aplicación.

Page 53
Enjuague y repita… 23

1.3 Enjuague y repita…


El monitoreo es el paso final en el ciclo de vida de desarrollo optimizado para dispositivos móviles, un ciclo
que se repite con cada iteración de tu aplicación. No es bueno descansar en los laureles después
un lanzamiento; Es hora de corregir errores y agregar nuevas características. La figura 1.11 resume los pasos.

• En Android, siga las pautas de diseño de materiales de Google


Diseño • En iOS, siga las pautas de la interfaz humana de Apple
• Piense en usabilidad y accesibilidad

• Utilice el control del código fuente


Código fuente
• Comete su código con frecuencia
controlar
• Git está bien integrado con Visual Studio

• Use Visual Studio en Mac o Windows para desarrollar su aplicación


• Para iOS, necesita una Mac para compilar, depurar y alojar el simulador
Desarrollar
• Visual Studio en Windows puede usar una Mac remota para crear aplicaciones de iOS.
Estudio visual Puede depurar en una pantalla de simulador remoto compartida a través de la red,
por lo que la Mac no necesita estar físicamente accesible, puede estar en la nube.

• Codifique su aplicación de manera que permita realizar pruebas


Prueba
• Prueba de unidad tanto como sea posible
UITest, • Crear pruebas de IU para probar automáticamente la interfaz de usuario
Test Cloud • Use Test Cloud para ejecutar sus pruebas o depurar en dispositivos que no tiene

• Use la integración continua (CI) para asegurarse de que su código se construya y que las pruebas pasen
Construir
• Ejecute las pruebas unitarias y las pruebas de IU de forma regular para obtener un ciclo de retroalimentación rápido
Estudio visual • Considere la implementación continua: implementación de compilaciones que pasan todas las pruebas a los usuarios
Centro de Aplicaciones regularmente, a través de herramientas como App Center

• Implemente versiones anteriores de su aplicación en probadores alfa y beta para obtener la mayor cantidad de datos del mundo real
Distribuir probando como sea posible
• Permitir a los usuarios proporcionar comentarios y generar errores
Estudio visual
• Responda a estos comentarios y corrija los errores rápidamente, luego vuelva a desplegarlos en alfa y
Centro de Aplicaciones
probadores beta

• Controle los bloqueos para que pueda corregir rápidamente los errores que los causan.
Monitor
• Monitoree los detalles de sus usuarios para asegurarse de que está apuntando a
Estudio visual audiencia correcta
Centro de Aplicaciones • Rastree los patrones de uso de su aplicación para saber en qué áreas enfocarse

Figura 1.11 Un resumen de todos los pasos para cada ciclo de una aplicación de producción

Page 54
24 C APÍTULO 1 Introducción de aplicaciones nativas multiplataforma con Xamarin

Mantenga sus ciclos pequeños para que sea fácil cambiar la dirección en función de los comentarios de su
monitoreo o sus usuarios. Pero no los haga tan pequeños que sus usuarios estén actualizando
sus aplicaciones con demasiada frecuencia (el lanzamiento al día siguiente es importante para corregir errores, pero mantenga las funciones
actualizaciones con al menos una semana de diferencia). Las actualizaciones periódicas son importantes porque hacen que su
los usuarios sienten que su aplicación está aquí para quedarse, y son buenos para promocionar su aplicación, ya que

https://translate.googleusercontent.com/translate_f 34/131
23/2/2020 Jim Bennett
Las tiendas destacan las aplicaciones actualizadas recientemente.
Ahora que ha visto este ciclo de vida en detalle, es hora de poner algo de esto en práctica.
Escribe y escribe un código que demuestre el poder de las aplicaciones de Xamarin. En el proximo
En el capítulo veremos un patrón de diseño que puede ayudarlo a construir Xamarin multiplataforma
aplicaciones al aumentar la cantidad de código multiplataforma que se puede compartir en iOS
y aplicaciones de Android. Luego seguiremos la tradición y construiremos un Hello World multiplataforma
solicitud.

Resumen
En este capítulo aprendiste
▪ Las aplicaciones nativas de Xamarin son aplicaciones integradas en C # que utilizan una versión del marco .NET
basado en Mono que se ha personalizado para ejecutarse en iOS y Android y usando
bibliotecas que envuelven los SDK de dispositivos nativos.
▪ Las aplicaciones Xamarin son mejores que las aplicaciones nativas escritas usando las herramientas del proveedor
porque obtienes todo el poder de una aplicación nativa con todas las características del dispositivo
y sistema operativo, pero están escritos en un lenguaje común, lo que le permite compartir
Lógica y código mon entre aplicaciones en diferentes plataformas.
▪ Xamarin tiene herramientas para el ciclo de vida de desarrollo optimizado para dispositivos móviles, cubriendo
desarrollo, prueba, construcción, distribución y monitoreo.
▪ Hay más en una aplicación móvil con calidad de producción que solo codificación. Tú primero
debe considerar el diseño de su aplicación para asegurarse de que sea adecuada para la plataforma
forma que estás apuntando. También debe codificarlo bien, asegurarse de que esté completamente probado, compilar
de manera reproducible, despliéguelo y vigílelo en busca de problemas una vez que esté en estado salvaje.

Página 55

2
Hola MVVM: creando un
aplicación multiplataforma simple
usando MVVM

Este capítulo cubre


▪ Quées MVVM y por qué es la mejor opción para cross-
plataforma de aplicaciones Xamarin
▪ De qué
se trata el patrón de diseño MVVM y por qué
desea usarlo para maximizar su código multiplataforma
▪ Configuración con Xamarin y la extensión MvvmCross
▪ Creando HelloCrossPlatformWorld, tu primer móvil Xamarin
aplicación
▪ Ejecutar su aplicación en iOS y Android

https://translate.googleusercontent.com/translate_f 35/131
23/2/2020 Jim Bennett
Por
fueralode
general, en esteen
la tecnología punto de un Sin
cuestión. libro, es tradicional
embargo, crear
para este unavoy
libro, aplicación HelloenWorld
a ir un poco para mostrar
contra
tradición y comience discutiendo el patrón de diseño MVVM (modelo-vista-vista-modelo)
charrán Luego nos ensuciaremos las manos con un código hacia el final de este capítulo.

25

Page 56
26 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

DISCUTIMOS MVVM PARA APLICACIONES CRUZADAS DE XAMARINA DE PLATAFORMA Los principios


discutido en este capítulo son para usar MVVM con aplicaciones Xamarin. A pesar de que
Estos siguen los principios para MVVM en otras plataformas, como el escritorio
Aplicaciones de Windows o la web, hay mucho más para las aplicaciones de Xamarin. Si has
hecho MVVM antes (tal vez con WPF) todavía vale la pena leer este capítulo como
Hay algunas diferencias importantes.

2.1 ¿Qué son los patrones de diseño de la interfaz de usuario?


Con el tiempo, los desarrolladores han encontrado y resuelto
los mismos problemas una y otra vez Fuera de esto tiene
Sqrt
vienen un conjunto de soluciones abstractas que se pueden aplicar
cuando construyas tu código. Estos se conocen como diseño.
400
patrones : soluciones repetibles a problemas comunes
que ocurren al diseñar y construir software.
Crear aplicaciones que interactúen con el usuario a través de

20
Una interfaz de usuario (UI) no es diferente. Hay stan-
problemas que los desarrolladores quieren resolver, y un Raíz cuadrada
varios patrones han surgido como soluciones para
estos problemas.
Consideremos una calculadora simple de raíz cuadrada
aplicación llamada Sqrt que tiene un cuadro de texto en el que puedes poner un
Figura 2.1 Una raíz cuadrada simple
número y un botón. Cuando tocas el botón, aplicación de calculadora que calcula el
calcula la raíz cuadrada del número en el raíz cuadrada de un número dado
cuadro de texto y muestra la respuesta en una etiqueta. Un examen-
El conjunto de esta aplicación se muestra en la figura 2.1.
La forma más sencilla de escribir esta aplicación es conectar el botón a un evento que tome el
valor directamente desde el cuadro de texto, calcula la raíz cuadrada y escribe el valor en un
etiqueta. Todo esto se puede hacer en el archivo de código subyacente para la interfaz de usuario. Simple y todo en uno
clase. La siguiente lista tiene un pseudocódigo para el tipo de cosas que podría escribir.

Listado 2.1 Pseudocódigo para agregar números mediante cableado a la interfaz de usuario directamente

Escucha el clic El número viene de


evento del botón leyendo el valor de la
Propiedad de texto del cuadro de texto.
MyAddButton.Click + = (s, e) =>
{
var número = double.Parse (NumberTextBox.Text);
var sqrt = Math.Sqrt (número);
MyResultLabel.Text = sqrt.ToString ();
}
Una vez que se calcula la raíz cuadrada, el
La propiedad de texto de la etiqueta se establece directamente.

Aunque esto parece simple, tiene varios defectos.

57
MVVM: el patrón de diseño para aplicaciones Xamarin 27

Primero, esto no es fácilmente comprobable. Solo puedes probar iOS Androide

esta aplicación actualizando el valor en el cuadro de texto y Solicitud C# C#


capa
tocando el botón Sería mejor si pudieras
escribir pruebas unitarias para que pueda probar mediante programación
Capa de interfaz de usuario
C# C#
el código, que abarca múltiples casos, incluido el borde
casos, como entradas faltantes o grandes o negativas
números. De esta forma, podría ejecutar un conjunto de
Negocio
C#
prueba de forma rápida y repetible cada vez que cambia capa lógica

tu codigo.
En segundo lugar, esto no es multiplataforma. Uno de los rea-
hijos para crear aplicaciones con Xamarin es para que las partes Figura 2.2 Las aplicaciones de Xamarin son
escrito en C # para que pueda compartir cualquier
de tu aplicación se puede escribir en un código compartido que funcione
lógica de negocios común mientras

https://translate.googleusercontent.com/translate_f 36/131
23/2/2020 Jim Bennett
tanto en iOS como en Android. Si no
tu cálculo es esto. Pensar tener una IU específica de plataforma.
conectado directamente a la vista, puede hacer
volver a las capas introducidas en el capítulo 1, que se muestran en la figura 2.2.
En una aplicación Xamarin tenemos tres capas:
▪ Capa de aplicación: esta es una pequeña parte del código que hace que su aplicación sea ejecutable
en cada plataforma y tiene diferentes implementaciones específicas de plataforma para iOS
y Android
▪ Capa de interfaz de usuario: la capa de interfaz de usuario también tiene implementaciones separadas específicas de la plataforma para
iOS y Android.
▪ Capa de lógica de negocios: la capa de lógica de negocios se comparte entre las dos plataformas.
formas

Para ajustar el código de la calculadora en esta estructura, necesitaría tener su código de cálculo
en la capa de lógica de negocios multiplataforma, y el botón, cuadro de texto, etiqueta y todos los
cableado en la capa de interfaz de usuario. Este es el tipo de problema que todos los desarrolladores de UI encuentran en un
diariamente y, como era de esperar, hay un patrón de diseño para ayudar con esto: MVVM.

2.2 2.2 MVVM: el patrón de diseño para aplicaciones Xamarin


MVVM (model-view-view model) es el patrón de diseño más popular para cross-plat-
forman aplicaciones creadas con Xamarin, y tiene un historial de ser un diseño muy exitoso
patrón para crear aplicaciones de escritorio de Windows usando WPF, aplicaciones Silverlight y ahora Win-
Dows 10 aplicaciones UWP. Incluso ha llegado a la web con marcos como knock-
out.js usándolo. Cuando Xamarin diseñó Xamarin.Forms, cuyo objetivo era tener como
compartiendo mucho código posible, los principios de MVVM se integraron en
ing marco de inmediato.
Piense en las tres capas en la aplicación Xamarin. Estas tres capas permiten un rea
gran cantidad de código compartido, pero podemos hacerlo mejor. En la capa UI hay realmente
dos capas: los widgets de IU reales y algo de lógica en torno a estos widgets. Por ejemplo,
podríamos poner algo de lógica alrededor de la etiqueta de respuesta para que solo sea visible una vez que
raíz cuadrada ha sido calculada. Esto expande nuestras tres capas a cuatro.

58
28 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

La Figura 2.3 muestra cómo se verían las capas si iOS Androide


podríamos mover esta lógica de IU a código compartido. Si nosotros
App
C# C#
hecho esto, la etiqueta en nuestro ejemplo estaría en la interfaz de usuariocapa
capa, y la lógica que decide si debería
estar visible u oculto estaría en la plataforma cruzada Capa de interfaz de usuario
C# C#

Capa lógica UI. Esta es una excelente manera de hacer las cosas: estamos
maximizando la reutilización del código abstrayendo la lógica de la interfaz
Lógica de
de lausuario
interfaz de usuario
C#
capa
en código multiplataforma.
MVVM ayuda con esta división de la interfaz de usuario y
Su lógica. Este patrón se nombra según los tres
Negocio
C#
capas que usa en su aplicación, como se muestra en la figura capa lógica

2.4. Veamos estas capas en el contexto de nuestro


ejemplo de calculadora:
Figura 2.3 Para maximizar la reutilización del código,
▪ Modelo: sus datos y lógica de negocios. sería bueno tener lógica de interfaz de usuario en
El modelo son los datos, la lógica empresarial y código compartido
acceso a cualquier recurso externo (como web
servicios o bases de datos) definidos en términos de
dominio, y esto se asigna a la capa de lógica de negocios en nuestra aplicación Xamarin. En nuestro
Por ejemplo, el modelo contiene el número, la lógica para calcular la raíz cuadrada,
y el resultado
▪ Ver: la interfaz de usuario real, botones, controles de texto y todos los demás widgets.
La vista es la interfaz de usuario con todos sus widgets y diseños, y esto se asigna a parte de
UI capa y contiene los widgets de la interfaz de usuario (el cuadro de texto, botón y etiqueta). Esto es un
vista pasiva, por lo que no tiene ningún código para obtener o establecer los valores o para manejar
eventos, como el clic del botón.
▪ Ver modelo: los datos y la lógica de la interfaz de usuario.
Para nuestra aplicación de calculadora, tiene propiedades que representan los números en
el modelo: el valor de entrada y el resultado. También tiene una propiedad de comando que
envuelve la lógica de cálculo de raíz cuadrada en el modelo en un objeto (más sobre
comandos en el siguiente capítulo). El modelo de vista conoce el modelo pero
No tiene conocimiento de la vista.

Además de estas tres capas, tiene un aglutinante , una capa de unión que puede imaginarse como
pegamento que conecta el modelo de vista a la vista. Esto elimina la necesidad de escribir boiler-
código de placa para sincronizar la interfaz de usuario: el aglutinante puede observar los cambios en la vista
modelar y actualizar la vista para que coincida, o actualizar el modelo de vista para que coincida con los cambios
realizado por el usuario en la interfaz de usuario. Este aglutinante está acoplado libremente en lugar de estar estrechamente acoplado,
y la conexión a menudo se realiza en función de las propiedades de cableado en la vista y la vista
modelo basado en sus nombres (por lo tanto, en el caso de un enlace entre una propiedad llamada
Texto y una propiedad llamada Nombre , en el tiempo de ejecución, la carpeta usará la reflexión para asignar
estos valores de cadena a las propiedades subyacentes).

https://translate.googleusercontent.com/translate_f 37/131
23/2/2020 Jim Bennett

Page 59
MVVM: el patrón de diseño para aplicaciones Xamarin 29

Ver 1. El enlace mantiene los datos en


sincronizar entre la vista y el
ver modelo, y conecta eventos
Unión
hasta ver modelos de comandos.
2. Las actualizaciones del modelo de vista
Ver modelo
el modelo basado en
cambios empujados desde
La capa de unión. 3. Los cambios de estado en el modelo son
pasado de nuevo al modelo de vista,
que luego puede notificar el enlace
Modelo
que algo ha cambiado, entonces
el enlace puede mantener la vista en
sincronizar con los cambios.

Figura 2.4 MVVM tiene un modelo, un modelo de vista, una vista y una capa de enlace que mantiene la vista
y ver el modelo sincronizado y conecta eventos en la vista al modelo de vista.

Reflexionando sobre la reflexión


Si nunca ha oído hablar de la reflexión antes, es una parte de la API de C # que le permite
consultar detalles sobre una clase: puede descubrir propiedades, campos, métodos o eventos.
Una vez que haya descubierto los detalles, también puede ejecutar el código. Por ejemplo, puedes
encontrar una propiedad basada en su nombre y luego obtener el valor de esa propiedad de un par-
instancia ticular de esa clase. La reflexión también es común en otros idiomas, como
Java: la reflexión de C # es básicamente la misma que la reflexión de Java.

Esto es ideal para vincular: si vincula una propiedad llamada Nombre, el código de vinculación puede usar
reflexión para encontrar una propiedad en su clase de modelo de vista con ese mismo nombre, y luego
puede obtener el valor en su instancia de modelo de vista.

Para nuestra aplicación de calculadora, el enlace conectaría el cuadro de texto, el botón y la etiqueta en
la interfaz de usuario a las propiedades equivalentes y un comando en el modelo de vista.
Hay un poco de magia involucrada en hacer que esta carpeta funcione, y esto suele ser
implementado en un marco MVVM, una biblioteca de terceros que le brinda un conjunto de
clases base que proporcionan la implementación de este patrón. Cubro cómo funciona esto más tarde
en este capítulo.

MARCOS MVVM Existen múltiples marcos MVVM que funcionan con


Aplicaciones nativas de Xamarin, como MvvmCross, MVVM Light y Caliburn.Micro.
Aunque cada uno tiene diferencias, todos siguen los mismos principios básicos.
y hacer aproximadamente las mismas cosas. Más adelante en este libro usaremos MvvmCross,
pero todo en este libro es aplicable a la mayoría de los marcos.

Por ejemplo, como se muestra en la figura 2.5, podríamos tener un cuadro de texto en nuestra aplicación de calculadora
IU que está vinculada a una propiedad Number . Esto significa que en tiempo de ejecución intentará encontrar un
propiedad pública llamada Número en el modelo de vista que está obligado a usar la reflexión,

60
30 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

Sqrt La propiedad Text del TextBox está vinculada a una propiedad


llamado "Número" en el modelo de vista. El aspecto vinculante
arriba la propiedad "Número" en el modelo de vista y encuentra
400 usando la reflexión

√ El enlace escucha las actualizaciones de la propiedad Text de


TextBox (generalmente a través de un evento modificado por texto generado por
20 el cuadro de texto). Cuando el usuario cambia el texto, el enlace
actualiza la propiedad Number en el modelo de vista.
Raíz cuadrada
El enlace también escucha las actualizaciones de Number. Cuando
la propiedad cambia, actualiza la propiedad Text del
TextBox en la interfaz de usuario.

Caja de texto Ver modelo


Unión
texto de cadena pública {get; set;} Número de cadena pública {get; set;}

La Figura 2.5 Enlace mantiene el valor de la vista sincronizado con el valor del modelo de vista.

y mostrará la cadena contenida en esa propiedad en el cuadro de texto. Si el usuario

https://translate.googleusercontent.com/translate_f 38/131
23/2/2020 Jim Bennett
cambia
para queelcoincida
valor dentro delque
con lo cuadro de texto,
ha escrito actualizará
el usuario. el contrario,
Por el valor de lasipropiedad
el valor deNumber
la propiedad Number en
el modelo de vista cambia, el enlace actualizará el cuadro de texto para que coincida.
A la carpeta no le importa cuál es el tipo de clase subyacente del modelo de vista que eres
usando, solo que tiene una propiedad pública llamada Número de la que puede extraer el valor.
En algunos de los marcos MVVM, ni siquiera le importa si la propiedad está allí o no.
Si no puede encontrar la propiedad, solo la trata como un valor vacío. Este acoplamiento suelto es lo que
hace que MVVM sea especialmente potente: permite que los modelos de vista sean completamente independientes de
la vista, para que pueda escribir pruebas unitarias contra el modelo de vista que simule la IU sin
preocupándose por el código UI que se interpone en el camino. También es compatible con la reutilización de código, por lo que una vista podría
pegarse a cualquier modelo de vista que tenga propiedades con los nombres que espera.
La Figura 2.6 amplía las figuras anteriores al mostrar cómo estas capas se asignan a
tres capas de MVVM:
▪ Capa de aplicación: la capa de aplicación es una que realmente no se incluye en MVVM puro.
patrón de diseño, pero los diferentes marcos MVVM proporcionan alguna aplicación
características de la capa. Esto nos permite tener un código multiplataforma en nuestra capa de aplicación
que puede controlar la lógica de la aplicación, como qué vista se muestra primero y cómo las diferencias
Las clases ent de la aplicación están conectadas juntas, como definir qué modelo de vista es
usado para cada vista.
▪ Capa de interfaz de usuario: la capa de interfaz de usuario es nuestra capa de vista, y este es un código específico de la plataforma.
▪ Encuadernación -La unión entre la capa de interfaz de usuario y la capa de lógica de interfaz de usuario es la
aglutinante: el pegamento que conecta la capa de la interfaz de usuario con su capa lógica. Esto suele ser un

Página 61
¿Qué es el código multiplataforma? 31

mezcla de plataforma cruzada y plataforma iOS Androide

código específico proporcionado por un tercero C# C#


App
marco de referencia.
capa
▪ Capa lógica UI: la capa lógica UI es nuestra C#

capa de modelo de vista. Proporciona lógica para


la interfaz de usuario y otras interacciones de dispositivosCapa
ende interfaz de usuario
C# C# Ver

un camino multiplataforma. Parte de esta lógica es Unión


conversión de valor: conversión de datos
Lógica de la interfaz de usuario Ver
en sus objetos de dominio a los datos en el capa
C#
modelo

UI Por ejemplo, podría modelar un


usuario en su dominio con un nombre
y apellido pero en la interfaz de usuario quiero Negocio
C# Modelo
capa lógica
muestra el nombre completo. El modelo de vista será
proporcionar esta conversión de valor por concat-
atacando los nombres y dando una cuerda
Figura 2.6 Las diferentes capas de ajuste MVVM
valor que mostrará la interfaz de usuario. con las diferentes capas de una aplicación Xamarin.
▪ Capa de lógica de negocios: la lógica de negocios
capa es la capa modelo. Contiene datos, objetos de dominio, lógica y conexión.
Actividad con recursos externos como bases de datos o servicios web. De nuevo, esto es cruzado
plataforma.

UNA LECCIÓN DE HISTORIA RÁPIDA MVVM existe desde 2005 y fue desarrollada
operado por dos arquitectos de Microsoft, Ken Cooper y Ted Peters. Fue pri-
Marily creado para su uso con la nueva pila de tecnología de interfaz de usuario que sale de
Microsoft llamó a WPF, y aprovecha el enlace de datos que era una característica clave
de WPF. En WPF, escribe su interfaz de usuario utilizando XAML, un lenguaje de marcado basado en la interfaz de usuario,
y en este XAML puede vincular las propiedades de un widget de IU a propiedades
definido en el contexto de datos de la vista, esencialmente el modelo de vista. Esta
permitió a los expertos en UI / UX diseñar la UI utilizando más herramientas basadas en diseñadores,
y simplemente conectar los widgets, en función de sus nombres, al código escrito inde-
pendiente de los desarrolladores.

2.3 ¿Qué es el código multiplataforma?


Algunas de las capas en nuestra aplicación basada en MVVM usan código multiplataforma, específicamente, parte
de la capa de aplicación, la capa de lógica de interfaz de usuario (modelo de vista) y la capa de lógica de negocios (modelo).
La razón de esto es simple: estamos creando una aplicación para iOS y Android, por lo que
la aplicación deberá funcionar de la misma manera en ambas plataformas, usar el mismo tipo de datos y
tener aproximadamente la misma lógica de UI. Tiene mucho sentido construir esto una vez y usar el
mismo código en ambas aplicaciones: código que escribimos una vez y puede ejecutarse en iOS y Android.
El término código multiplataforma ya ha aparecido mucho en este libro, y continuará
ser un tema en todo momento. Pero, ¿qué queremos decir exactamente cuando hablamos de cross-
código de plataforma en C #?

https://translate.googleusercontent.com/translate_f 39/131
23/2/2020 Jim Bennett
Page 62 32 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

Las aplicaciones nativas multiplataforma no son realmente multiplataforma


En el mundo de Xamarin hablamos de aplicaciones nativas multiplataforma, pero estas no son ciertas
aplicaciones multiplataforma donde se ejecutará exactamente la misma aplicación en todas las plataformas. Tampoco es
multiplataforma en que todo el código se ejecuta en todas las plataformas (con una capa de aplicación oculta).

Lo que quiero decir aquí es que tenemos dos aplicaciones, una que se ejecuta en iOS y otra que se ejecuta
en Android, ambos desarrollados usando el mismo idioma y compartiendo una gran parte de
el código. Son multiplataforma en que la lógica de negocios (e idealmente la lógica de la interfaz de usuario)
es verdaderamente multiplataforma y la interfaz de usuario y capa de características específicas de dispositivo más pequeñas posibles
está construido para ser específico de la plataforma.

El patrón de diseño MVVM es muy adecuado para ayudarlo a obtener la mayor cantidad de código compartido
como sea posible.

2.3.1 Bibliotecas de clases estándar .NET


Cuando Microsoft lanzó .NET Framework, proporcionaron un conjunto de API que funcionan
en Windows, y con cada versión del marco agregaron más API que
los desarrolladores pueden usar. Con el tiempo, se agregó soporte para más plataformas, como Micro-
Silverlight de soft (aplicaciones que se ejecutan en un navegador) o la Tienda Windows (aplicaciones que se ejecutan en un
sandbox y distribuido a través de una tienda de aplicaciones de Microsoft). Estas plataformas diferentes no
proporciona las mismas capacidades, por lo que el código escrito en el núcleo de .NET Framework podría
no funciona en Silverlight si requiere API que Silverlight no implementó (o no pudo)
ment. La solución inicial a esto fueron las bibliotecas de clases portátiles (PCL), bibliotecas que
obtuvo un subconjunto común de las API .NET que se ejecutarían en todas las plataformas. Xamarin
aprovechó esto, usando el mismo modelo para permitirle escribir clases portátiles
bibliotecas dirigidas al subconjunto de .NET Framework que se ejecuta en iOS o Android.
Esto funcionó de una manera, pero causó mucha confusión. Las PCL vienen en pro-
archivos: un perfil es un subconjunto definido que funcionará en una combinación particular de
plataformas Un perfil funcionaría en iOS, Android y Windows en .NET 4.5,
mientras que otro también se ejecutaría en iOS y Android, pero requiere .NET 4.6. Esta
significaba que no solo necesitarías elegir el perfil adecuado para las plataformas que
estaban dirigidos, pero también necesitaría bibliotecas de terceros para apuntar también a un compatible
perfil. Si su perfil incluía .NET 4.5 en Windows, no podría usar una biblioteca que
usó un perfil que necesitaba .NET 4.6, por ejemplo.
Las cosas ahora están mucho mejor, gracias a una nueva iniciativa de Microsoft llamada .NET
Estándar. Este es un intento de estandarizar las diferentes plataformas .NET en una versión
conjunto mencionado de API. Cada plataforma, como Xamarin iOS, Xamarin Android o el
.NET Framework en Windows implementa una versión particular del estándar, también
como todas las versiones anteriores Este es un estándar inclusivo, por lo que si una plataforma admite .NET
Estándar 1.6, también incluye 1.5, 1.4, y así sucesivamente, hasta 1.0. La idea

Page 63
¿Qué es el código multiplataforma? 33

detrás de esto es simple: cada versión tiene más API disponibles que la versión anterior,
y su código puede usar bibliotecas que se dirigen a la misma o una versión anterior de la
estándar. Por ejemplo, si su código apunta a .NET Standard 1.6, puede usar una biblioteca
que apunta a 1.4. Puede pensar en .NET Framework en Windows como el más completo
conjunto completo de API y cada versión de .NET Standard como una implementación más completa
ción de .NET Framework completo.
Puede leer más sobre las bibliotecas .NET Standard y ver qué versión del estándar
Dard es implementar mediante qué versión de cada plataforma en Microsoft Docs en
http://mng.bz/sB0y . Al momento de escribir, Xamarin iOS y Android admite ver-
sion 2.0, por lo que puede usar código que apunte a 2.0 o anterior desde sus aplicaciones Xamarin. Ser
Sin embargo, tenga en cuenta que la orientación a versiones superiores puede limitar las plataformas que admite. A
Al momento de escribir, UWP solo admite 1.4, por lo que si decide agregar un proyecto de UWP a
sus aplicaciones Xamarin para admitir Windows 10, deberá garantizar los proyectos principales
utilizado por su objetivo de aplicación 1.4 o inferior.
Estas bibliotecas .NET Standard son perfectas para la capa multiplataforma en su
Aplicaciones de Xamarin. El conjunto de API que implementan las bibliotecas .NET Standard incluye todos
los bits que funcionarían en todas las plataformas (colecciones, tareas, E / S simple y red)
trabajando. Lo que no está incluido es algo específico de una plataforma, como el código de la interfaz de usuario.
Esto se deja al código específico de la plataforma para implementar. .NET Standard es solo una API
especificación, no es la implementación real. Debajo del capó, el código que
constituye el subconjunto de las API .NET no es lo mismo en todas las plataformas, cada plataforma
implementa sus funciones utilizando la API nativa que proporciona la plataforma. Pero el
la interfaz con él (las clases y los espacios de nombres) son los mismos.
Cuando escribes tu aplicación multiplataforma,
iOS Androide
quieres tanto código como sea posible dentro
Bibliotecas estándar .NET, ya que este es el código C# C#
App
eso es compartido Pensando nuevamente en las capas capa

https://translate.googleusercontent.com/translate_f 40/131
23/2/2020 Jim Bennett
C # (.NET Standard)
en nuestra aplicación, puedes ver fácilmente qué capas
viviría en una biblioteca .NET Standard, como
C# C#
se muestra en la figura 2.7. Capa de interfaz de usuario Ver

Para asignar esto a la estructura del proyecto, eres Unión

probablemente solía en una solución de C #, tendrías Lógica de la interfaz de usuario Ver


C # (.NET Standard)
(al menos) tres proyectos. Uno (o más) lo haría capa modelo

ser un proyecto .NET Standard que contenga todo


su interfaz de usuario multiplataforma y lógica de negocios
Negocio
código. Otro sería un proyecto de aplicación para iOS capa lógica
C # (.NET Standard) Modelo

que contiene el código de la aplicación iOS y el


Código de IU de iOS. Y el último sería un
Aplicación de Android que contiene el Android- Figura 2.7 Las capas multiplataforma en un
IU específica y código de aplicación. Esto es ilus- la aplicación móvil se implementa en .NET
Bibliotecas estándar.
tratado en la figura 2.8.

Página 64
34 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

El proyecto Droid contiene


la aplicación de Android y es
Específico de Android.

El proyecto principal que contiene


el código multiplataforma es
una biblioteca estándar .NET.

El proyecto de iOS contiene el


Aplicación para iOS y es específica de iOS.

Figura 2.8 Una aplicación multiplataforma típica contendría una biblioteca .NET Standard con el código central,
una aplicación de Android con código específico de Android y una aplicación de iOS con código específico de iOS

Ahora que ha visto algunos de los conceptos básicos, creemos una aplicación de ejemplo simple usando el
MvvmCross MVVM framework.

2,4 Comenzando: creando su primera solución


Según lo prometido, ahora va a crear una aplicación Hello World, una aplicación simple que
no hace mucho, pero le permite estar seguro de que su entorno de desarrollo es
funciona correctamente y para ver lo simple que es crear una aplicación que funcione. Porque el grande
La fuerza de Xamarin es permitirle crear aplicaciones multiplataforma con una gran cantidad
de código compartido, creará dos aplicaciones: una para iOS y otra para Android.
Compartirán una biblioteca central común con toda la lógica empresarial, en la medida en que usted
puede tener lógica de negocios en una aplicación Hello World. También aprovecharás lo que has aprendido
en este capítulo y compilarlo usando MVVM. El framework MvvmCross que usarás
aquí le ahorrará escribir mucho código repetitivo. Este marco es muy popular
con desarrolladores que crean aplicaciones Xamarin multiplataforma, y es muy activo
sostenido y mejorado.

MVVMCROSS Cubriremos lo que necesita saber sobre MvvmCross para


construya sus aplicaciones de ejemplo en este libro. Si quieres leer más al respecto (o
contribuir al marco: es de código abierto y da la bienvenida a contribuir
opciones) luego dirígete a https://mvvmcross.com .

Seguiremos estos pasos para lograr esto:


▪ Crear y ejecutar una nueva aplicación multiplataforma: crearemos una multiplataforma
Aplicación MvvmCross usando una extensión de Visual Studio que instalaremos. Una vez esto
Si se ha creado la solución, la activaremos en iOS y Android como comprobación de sanidad.
▪ Probar que el código es multiplataforma: solo para demostrar que tenemos una aplicación multiplataforma con
código compartido, modificaremos el código en un lugar y veremos el efecto que tiene
en ambas aplicaciones.

Página 65
Comenzando: creando su primera solución 35

A pesar de usar MvvmCross aquí y en las aplicaciones que construiremos en capítulos posteriores, el objetivo es
no para encerrarte en este marco. Solo usaremos algunas partes pequeñas, y el
Los principios detrás de esas partes son bastante estándar para el patrón MVVM. Estos principios
Los ples son fáciles de aplicar cuando se usan otros marcos, como MVVM Light.

https://translate.googleusercontent.com/translate_f 41/131
23/2/2020 Jim Bennett
2.4.1 Requisitos: qué hardware o software necesita
para cada plataforma móvil?
En el capítulo 1 discutimos el soporte de la plataforma de Xamarin y las herramientas que puede usar.
Aquí hay un repaso rápido:
▪ Si tiene una PC con Windows, debe instalar Visual Studio 2017 y asegurarse de que
La carga de trabajo "Xamarin" está marcada en el instalador.
▪ Si tiene una Mac, debe instalar Visual Studio para Mac, que incluye
Visual Studio, así como los componentes de iOS y Android Xamarin, el
Android SDK y el emulador de Android de Google. También necesitas instalar Xcode
de la Mac App Store para el desarrollo de iOS.
▪ Si desea desarrollar aplicaciones iOS con Visual Studio en Windows, debe
tener acceso a una Mac con Xamarin y Xcode instalados.
▪ Siempre instale o actualice a las últimas versiones estables de todos los componentes, como
la última versión de VS 2017, el último VS para Mac, el último Xcode y el lat-
es Android SDK y herramientas. Para instalar las últimas herramientas y SDK de Android, deberá
necesita usar el administrador de Android SDK, disponible en Visual Studio yendo a
Herramientas> Android> Android SDK Manager en Windows o Herramientas> SDK Manager
en la Mac

Este libro no cubre la instalación.


Los instaladores de Visual Studio cambian con bastante frecuencia, por lo que es difícil mantenerse al día con ellos en
impresión. Aunque este libro describe lo que se necesita, no cubre la instalación y
configuración en detalle.

Al momento de escribir, el instalador de Visual Studio para Mac le brinda todo lo que necesita.
necesidad en Mac, incluidos los SDK y emuladores de Android. Lo único extra que necesitas
instalar es Xcode desde Mac App Store para construir aplicaciones iOS.

En Windows, el instalador de Visual Studio 2017 instala todo, siempre que marque
las opciones correctas para el desarrollo multiplataforma, los SDK de Android y los emuladores,
que cambian un poco con cada actualización. Si está utilizando una máquina virtual de Windows en
su Mac para ejecutar Visual Studio, deberá habilitar su máquina virtual para alojar un
máquina virtual anidada si desea ejecutar los emuladores de Android: consulte el documento VM
Indicación de cómo hacer esto. Si usa una PC, necesitará una CPU Intel con virtual-
ization habilitado (la mayoría de las CPU modernas tienen esto). Los requisitos del sistema para ejecutar
los emuladores se enumeran en el sitio de Android Studio ( http://mng.bz/hkXV ).

Página 66
36 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

(continuado)
Si te quedas atascado, Xamarin tiene una excelente documentación en su sitio web ( https: // aka
.ms / XamDocs ) que cubre todo lo que necesita para la instalación y configuración. El sitio también
tiene foros útiles con una gran comunidad de usuarios, y los propios ingenieros de Xamarin si
Tienes un problema particularmente extraño. Y obviamente, siempre hay Stack Overflow.

En este punto, voy a asumir que ya tienes todo lo que necesitas instalado. Si
No, ahora sería un buen momento para hacerlo.
Para esta pequeña aplicación de prueba, solo vamos a probar en el emulador de Android y iOS
simulador, así que no se preocupe si no tiene un dispositivo físico para usar. Si tienes un
dispositivo físico, luego póngalo a un lado por ahora y simplemente use el emulador / simulador como
hay que configurar un poco el dispositivo para ejecutar y depurar aplicaciones en dispositivos reales. En
Android es simple, pero en iOS es un poco más complicado. Estaremos discutiendo esto
en el capitulo 13.
Como se mencionó anteriormente, usaremos el marco MvvmCross, y afortunadamente para
Para nosotros, hay una extensión disponible para Visual Studio que nos permite crear un nuevo cross-
solución de plataforma Esta solución contiene una biblioteca central y aplicaciones específicas de plataforma para
todas las plataformas compatibles (así que en Visual Studio para Mac obtienes una aplicación iOS y un
Aplicación Android; en Windows es iOS, Android, WPF y UWP). Viendo como estaremos
instalando una extensión, y los proyectos que creamos necesitarán paquetes NuGet, usted
Necesito acceso a internet. Esto puede sonar obvio, pero si estás en una cafetería, ahora
sería un buen momento para obtener su contraseña de WiFi.

2.4.2 Creando la solución


Veamos cómo instalar la extensión y crear nuestra primera solución.
C REPETIR LA SOLUCIÓN USANDO V ISUAL S TUDIO PARA M AC
Desde Visual Studio, seleccione Visual Studio> Extensiones. Aparecerá un cuadro de diálogo.
para permitirle agregar o eliminar extensiones. Desde aquí, seleccione la pestaña Galería, asegúrese de
el repositorio está configurado en Visual Studio Extension Repository y busca MvvmCross
Paquete de plantillas bajo Extensiones IDE, o usando la búsqueda (ver figura 2.9). Seleccione
esto y haga clic en Instalar. Luego haga clic en Instalar en el cuadro de diálogo que aparece.

https://translate.googleusercontent.com/translate_f 42/131
23/2/2020 Jim Bennett

Page 67
Comenzando: creando su primera solución 37

La plantilla MvvmCross Visual Studio tiene múltiples repositorios Ingrese el texto aquí
El paquete está bajo IDE cubriendo versiones estables de extensiones para buscar el
Extensiones en el árbol. así como versiones alfa y beta. Galería de extensión.

Puede instalar extensiones de archivos en su lugar Haga clic en Instalar para instalar la extensión.
de desde el repositorio si es necesario.

Figura 2.9 Selección del paquete de plantillas MvvmCross del administrador de extensiones de Visual Studio

Una vez que esté instalado, es una buena idea reiniciar Visual Studio, ya que el nuevo tipo de solución
no aparecerá en el lugar correcto hasta que lo hagas.
Una vez que se reinicia Visual Studio, puede comenzar a crear una nueva solución. Usted puede
Acceda al cuadro de diálogo Nueva solución de tres maneras.
▪ Desde el menú, vaya a Archivo> Nuevo> Solución
▪ Uso del método abreviado de teclado Shift-Command-N ( ⇧ + ⌘ + N)
▪ Al hacer clic en el botón Nuevo proyecto en la parte inferior de la página Comenzar que se muestra
cuando abres Visual Studio por primera vez. De cualquier forma que elija, usted
luego se le presentará el cuadro de diálogo Nueva Solución (figura 2.10).

Página 68
38 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

https://translate.googleusercontent.com/translate_f 43/131
23/2/2020 Jim Bennett

Seleccione Otro> .Net, luego seleccione Ingrese el nombre del proyecto aquí.
Aplicación nativa de una sola página MvvmCross Por defecto, la solución está dada
de la sección MvvmCross. el mismo nombre que el proyecto

Visual Studio, de forma predeterminada, creará todos los archivos Puedes cambiar la carpeta
necesitaba llevar esto a un repositorio de Git, incluso El proyecto se crea aquí.
creando un archivo .gitignore apropiado para usted.

Figura 2.10 Los cuadros de diálogo Nueva solución que muestran la aplicación multiplataforma MvvmCross
plantilla de solución y establecer el nombre del proyecto

Página 69
Comenzando: creando su primera solución 39

Desde este cuadro de diálogo, seleccione Otro> .NET de la lista del lado izquierdo y luego seleccione Mvvm-
Aplicación nativa de página única cruzada de la lista en el medio. Haga clic en Siguiente. Sobre el
siguiente pantalla ingrese HelloCrossPlatformWorld como el nombre del proyecto y haga clic en Crear.
Esto creará una nueva solución para usted que contiene tres proyectos: un estándar .NET
proyecto principal (HelloCrossPlatformWorld.Core), una aplicación de iOS (HelloCrossPlatform-
World.iOS) y una aplicación de Android (HelloCrossPlatformWorld.Droid), como se muestra en la figura
ure 2.11. Una vez que se haya creado la solución, intentará descargar todos los NuGet
paquetes que necesita: verá la barra de estado en la parte superior que muestra Agregar paquetes. Esta
puede tomar un tiempo, dependiendo de la velocidad de su conexión a internet, y usted puede
se les pedirá que acepten algunos acuerdos de licencia a medida que se descargan. Tendrás que dejar
se descargan completamente antes de crear las aplicaciones.

Figura 2.11 Los tres proyectos que


son creados para ti en la nueva solución

POR QUÉ NO HELLOCROSSPLATFORMWORLD.ANDROID La convención para Android


aplicaciones es usar "Droid" en sus nombres en lugar de Android. Esto es porque el
el nombre del proyecto se convierte en el espacio de nombres predeterminado, y si tiene "<alguna-
cosa> .Android "en su espacio de nombres, puede obtener un choque con el global
Espacio de nombres "Android". Terminas ensuciando tu código con global :: Android
. <lo que sea> al usar directivas o tipos, lo que hace que sea más difícil de leer. Atenerse a
¡Droid, es más fácil!

C REACIÓN la solución usando V isual S Tudio PARA W INDOWS


Desde Visual Studio, seleccione Herramientas> Extensiones y actualizaciones. Seleccione la sección en línea en
a la izquierda y use el cuadro de búsqueda para buscar MvvmCross para Visual Studio (figura 2.12).
Hay varias extensiones con el mismo nombre y nombres similares, así que asegúrese de la que
install se llama "MvvmCross for Visual Studio" y es al menos la versión 2.0. Selecciónalo y
haga clic en el botón Descargar y haga clic en Instalar en el cuadro de diálogo que aparece.
Una vez que se haya descargado, se le pedirá que reinicie Visual Studio para instalar el
extensión, cierre Visual Studio y espere a que termine el instalador de la extensión. Después de este
ha terminado, reinicie Visual Studio y puede crear la nueva solución de dos maneras:
▪ Desde el menú Archivo seleccionando Archivo> Nuevo> Proyecto
▪ Al hacer clic en la opción Nuevo proyecto en la sección Inicio de la página de inicio
eso se muestra cada vez que abre Visual Studio

https://translate.googleusercontent.com/translate_f 44/131
23/2/2020 Jim Bennett

Page 70
40 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

Instalado te muestra las extensiones Haga clic en Descargar para descargar Escriba aquí para buscar
Ya lo tienes instalado. e instale la extensión. La galería de extensiones.

Actualizaciones muestra actualizaciones de Elija en línea para buscar las extensiones


extensiones y Visual Studio. disponible en la galería de Visual Studio.

Figura 2.12 Selección de la extensión MvvmCross para Visual Studio desde Visual Studio
Administrador de extensiones

En el cuadro de diálogo Nuevo proyecto (que se muestra en la figura 2.13), seleccione la sección MvvmCross
debajo de Visual C # a la izquierda, elija MvvmCross Single Page Native Application de
la lista en el medio, ingrese HelloCrossPlatformWorld como nombre del proyecto y haga clic en
OKAY. Windows tiene problemas con rutas de más de 256 caracteres, y algunos de los
los directorios que se crearán cuando se cree su aplicación tienen nombres largos, por lo que puede
desea asegurarse de que su solución se cree en una carpeta cercana a la raíz de una unidad. Si lo haces
en C: \ Users \ <username> \ Documents \ visual studio 2017 \ Projects, su ruta puede ser
demasiado largo.
Esto creará cinco proyectos para usted: un proyecto principal de .NET Standard, una aplicación de iOS, un
Aplicación de Android y un par de aplicaciones de Windows que cubren WPF y UWP. Solo somos
interesado en admitir iOS y Android aquí, para que pueda eliminar Universal Win-
dows y proyectos WPF seleccionándolos y presionando Eliminar o usando Eliminar de
el menú contextual del botón derecho. Esto te dejará con los mismos tres proyectos que en
Visual Studio para Mac: el proyecto principal, la aplicación iOS y la aplicación Android, como se muestra
en la figura 2.14.

Page 71
Comenzando: creando su primera solución 41

Seleccione Plantillas> Visual C #> MvvmCross, Si no quieres seleccionar una plantilla


luego seleccione MvvmCross Single Page desde el árbol, puede escribir "MvvmCross"
Aplicación nativa. aquí para encontrarlo rápidamente.

Ingrese el nombre del proyecto. Por Puedes cambiar el Visual Studio, de forma predeterminada, creará

https://translate.googleusercontent.com/translate_f 45/131
23/2/2020 Jim Bennett
por defecto, la solución está dada carpeta del proyecto es todos los archivos necesarios para llevar esto a un
el mismo nombre que el proyecto creado aquí. Repositorio de Git, incluso creando un
pero puedes cambiar la solución archivo .gitignore apropiado para usted.
nombre si quieres.

Figura 2.13 El cuadro de diálogo Nuevo proyecto, donde puede crear su nueva solución

Figura 2.14 Los tres proyectos


dejado en la solución después de eliminar
los no deseados

Conectar Visual Studio a una Mac para el desarrollo de iOS


No voy a cubrir esto en detalle aquí, ya que esto está bien documentado en Xamarin "Get-
ting Started ”, en el sitio del desarrollador en http://mng.bz/KbiM , y podría
Realmente cambie entre el momento de escribir y cuando está leyendo esto.

Esencialmente, sin embargo, debe permitir el inicio de sesión remoto en una Mac que ya tiene Xama-
Rin y Xcode instalados. Visual Studio luego se conecta a esta Mac para construir su aplicación iOS.
El proceso es bastante simple, y si usa una Mac alojada en la nube, su proveedor
debería poder proporcionar instrucciones sobre cómo configurarlo.

Page 72
42 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

2.4.3 ¿Qué acabamos de crear?


La extensión MvvmCross nos ha dado tres proyectos que nos interesan. Tenemos una
proyecto central multiplataforma y dos proyectos de aplicaciones. Estos proyectos hacen referencia a MvvmCross
Paquetes NuGet que proporcionan el marco MvvmCross MVVM.

Cuando crea este proyecto, los paquetes NuGet pueden no ser los últimos
Los paquetes NuGet están versionados. Puede instalar la versión 1.0 de un paquete desde
servidor público NuGet, y luego el autor podría actualizarlo a la versión 1.1. Entonces puedes
Actualice fácilmente el paquete NuGet desde Visual Studio.

Pero ten cuidado. A veces los paquetes pueden no ser compatibles con versiones anteriores. El Mvvm
Es posible que la extensión cruzada no siempre instale las últimas versiones de MvvmCross NuGet
paquetes, y si los actualiza, el código creado por la extensión probablemente
Todavía funciona, pero no hay garantías.

El proyecto central es una combinación de dos de nuestras capas: el negocio multiplataforma


capa lógica y la capa lógica de interfaz de usuario multiplataforma. Estas capas no necesitan existir en septiembre
proyectos arate: son solo capas conceptuales. El núcleo contiene un modelo de vista para el
aplicación más lógica de aplicación multiplataforma (discutiremos la capa de aplicación en
El siguiente capítulo). La figura 2.15 muestra la estructura de este proyecto en la plataforma de solución.
Notarás aquí que no tenemos ningún modelo. En este simple ejemplo, el
El modelo es solo una cadena que está envuelta dentro del modelo de vista (y jugaremos con
esta cadena un poco más tarde). Esto no es normal: en un caso del mundo real, el modelo de vista
necesita algo en la capa del modelo para que pueda representar el estado de la capa del modelo
y comportamiento. Por ahora, sin embargo, como este es un trivial Hello World, no hay una capa de modelo.
La aplicación específica de la plataforma y las capas de vista, así como el enlace, viven dentro del
dos proyectos de aplicaciones, uno para iOS y otro para Android, ya que el código para estas aplicaciones es

El proyecto central multiplataforma

Ver modelos en vivo en esta carpeta.

App.cs contiene multiplataforma


código de capa de aplicación.

Figura 2.15 La estructura del proyecto central multiplataforma

https://translate.googleusercontent.com/translate_f 46/131
23/2/2020 Jim Bennett
Page 73
Comenzando: creando su primera solución 43

Vistas en vivo aquí en iOS y


consiste en un guión gráfico
que define el diseño
y algo de código subyacente.

Android define vistas usando dos partes:


un archivo de diseño XML y algo de código subyacente.
Los archivos XML viven aquí.

El código subyacente para las vistas vive aquí.

Figura 2.16 La estructura de los proyectos de aplicaciones iOS y Android

plataforma específica. La estructura se muestra en la figura 2.16. En los próximos capítulos vamos a
entrar en más detalles sobre cómo Android e iOS definen sus capas de aplicación y
sus opiniones.

2.4.4 Construyendo y ejecutando las aplicaciones


Tenemos dos aplicaciones ahora, así que vamos a ejecutarlas y ver qué pasa. La figura 2.17 muestra
lo que verás cuando estén corriendo. En ambos casos tenemos una aplicación que tiene una edición
cuadro de texto capaz y una etiqueta. Si cambia el texto en el cuadro de texto, la etiqueta será
actualizado al instante.

Page 74
44 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

Figura 2.17 Nuestras aplicaciones Hello Cross-Platform World que se ejecutan tanto en Android como en iOS

https://translate.googleusercontent.com/translate_f 47/131
23/2/2020 Jim Bennett

Cuando usó la extensión MvvmCross para crear la solución, creó estos dos
aplicaciones para ti, ambas usando algún código común compartido.

Un NDROID
Comencemos por probar la aplicación de Android.

CAMBIO DE MAC A WINDOWS Los archivos de proyecto y solución creados por


Visual Studio para Mac son totalmente compatibles con Visual Studio en Windows,
y viceversa. Esto significa que si usa una herramienta y desea cambiar a
otro, puedes. También significa que puede cargar la solución de cualquier otra persona, independientemente
de qué herramientas se usaron para crearlo.

Lo primero que debes hacer es asegurarte de que la aplicación de Android sea el proyecto de inicio, así que haz clic derecho
y seleccione Establecer como proyecto de inicio. Una vez que esto esté seleccionado, verá opciones para elegir
ing el dispositivo para ejecutarlo en el menú.
En Visual Studio para Mac (a la izquierda en la figura 2.18), verá dos menús desplegables
menús en la esquina superior izquierda, y desde el segundo puede elegir el dispositivo para ejecutar:

Página 75
Comenzando: creando su primera solución 45

Figura 2.18 Los menús de selección de dispositivos Android

un emulador o un dispositivo físico (si tiene uno conectado). Visual Studio usa el
emuladores de Google e instala y configura dos de estos por defecto. Debieras
seleccione el emulador Acelerado x86, ya que será más rápido en una Mac; Emula basada en ARM
Los torres corren aproximadamente 10 veces más lento que la versión x86.
Visual Studio para Windows instala el Visual Studio Emulator para Android como parte
de su instalador (suponiendo que la opción estaba marcada cuando ejecutó el instalador), y lo hará
configure algunos de estos dentro de Visual Studio para que los use.
Estos emuladores vienen en diferentes tipos de hardware y diferentes versiones del sistema operativo Android
Sions. Tendrá que usar un emulador basado en x86 (es mucho más rápido que el ARM ver-
sion), y todos los emuladores x86 son básicamente iguales en términos de hardware, solo usando
Una versión diferente del sistema operativo Android. Por ahora, solo elija la última versión del sistema operativo y
ejecute la aplicación haciendo clic en el botón Ejecutar en la barra de herramientas o eligiendo Ejecutar>
Inicie la depuración en Visual Studio para Mac o Depuración> Inicie la depuración en Windows.
Siéntese y relájese mientras se crea su aplicación y se inicia el emulador.
Tenga en cuenta que la primera vez que se compile su aplicación, llevará mucho tiempo, hay
una serie de archivos SDK que Xamarin necesita descargar para construir un Android
aplicación, y los descarga la primera vez que su aplicación se crea sin comentarios en el
salida excepto que está construyendo. No mates la construcción, si lo haces, es posible que tengas que ...
ualmente limpie los archivos zip medio descargados. Si obtiene errores sobre archivos zip corruptos,
puedes encontrar información sobre cómo solucionarlos en la solución de problemas de Android de Xamarin
guía en http://mng.bz/MKSQ .

NO EJECUTE MÁS DE UN EMULADOR DE ANDROID Los emuladores de Android pueden ser


un poco quisquilloso a veces, ya que se ejecutan dentro de máquinas virtuales. Si intentas correr más
de uno, pueden congelarse y no comenzar. Si alguna vez haces que esto suceda
la pantalla del emulador permanece en negro y no pasa nada; ciérrela y cierre todo
otros emuladores que tenga en ejecución e intente nuevamente.

Page 76
46 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

Esta aplicación no hace mucho. Simplemente muestra las características muy básicas de MvvmCross. Si
Si cambia el texto en el cuadro de texto, la etiqueta a continuación se actualizará para reflejar esto. Bien
sumérgete en lo que sucede un poco más tarde, pero por ahora has superado el primer obstáculo:
Tienes una aplicación que se ejecuta. Vamos a seguir con iOS.

https://translate.googleusercontent.com/translate_f 48/131
23/2/2020 Jim Bennett
I OS

Construir y ejecutar la aplicación iOS es muy similar a Android. Primero, asegúrese de que la aplicación iOS
es el proyecto de inicio, tal como lo hizo para la aplicación de Android.
A continuación, debe seleccionar el dispositivo para ejecutar. Esto es ligeramente diferente de
Androide. Android siempre crea el mismo código para emuladores y dispositivos físicos, por lo que
todo lo que necesitas hacer es elegir el dispositivo. En Visual Studio para Mac, esto es lo mismo:
del menú desplegable, elija un simulador o un dispositivo físico si hay uno disponible
(a la izquierda en la figura 2.19). Desde aquí, seleccione el simulador de iPhone que prefiera,
aunque uno reciente siempre es bueno.

Figura 2.19 Los menús de selección de dispositivos iOS

Visual Studio para Windows es similar, aunque lo divide en dos menús desplegables
menús: uno para elegir un dispositivo físico o un simulador, y otro que muestra
los dispositivos o simuladores disponibles (a la derecha en la figura 2.19). En este caso, elija
iPhoneSimulator desde el primer menú, y seleccione el simulador de su elección desde
el segundo.
Una vez que se selecciona el simulador apropiado, ejecute la aplicación. Si estás usando Visual Stu-
dio para Mac, el simulador se ejecutará en tu Mac. Si está utilizando Windows, la simulación
tor se iniciará en su Mac o en su PC con Windows si tiene iOS
Simulador para Windows instalado.
Una vez que se active el simulador, verá la aplicación de muestra básica MvvmCross. Esto es
idéntico a la aplicación de Android: edite el texto y las actualizaciones de etiquetas para que coincidan. Temor-
algunos: su aplicación Xamarin se ejecuta en iOS sin ningún trabajo adicional.

Page 77
¿Es realmente una aplicación multiplataforma? 47

2.5 ¿Es realmente una aplicación multiplataforma?


Una de las grandes ventajas de Xamarin es poder escribir aplicaciones multiplataforma.
califique las aplicaciones para cada plataforma con código de núcleo compartido. La pregunta en tus labios ahora es
probablemente "¿es esto lo que estamos viendo aquí?" ¡La respuesta es sí! El iOS y Android
los proyectos tienen parte de la capa de aplicación (el código para ejecutar realmente una aplicación),
y la capa de vista (la interfaz de usuario se define en un código específico de la plataforma), pero el núcleo de cada
Lo está en un proyecto central compartido. Esto es bastante simple de probar, así que hagamos un simple
cambio de código para demostrarlo.
En las aplicaciones que ha ejecutado en Android e iOS, tiene un cuadro de texto con "Hola Mvvm-
Cross ”en él, y una etiqueta que coincide con este texto, actualizándose cada vez que el texto cambia.
Cambiemos ahora el valor inicial de este texto.
En el proyecto Core hay una carpeta ViewModels (figura 2.20), y dentro de esta hay un
clase view-model llamada FirstViewModel (en el archivo FirstViewModel.cs). Mira el
hola campo, y verás que está inicializado en Hello MvvmCross . Actualiza esto para que sea Hola
Xamarin en acción de la siguiente manera.

El proyecto central multiplataforma

Ver modelos en vivo en esta carpeta.

FirstViewModel es el que nosotros


quiero editar

Figura 2.20 La estructura del proyecto principal que muestra la ubicación de la clase FirstViewModel

Listado 2.2 Campo hola actualizado en FirstViewModel

https://translate.googleusercontent.com/translate_f 49/131
23/2/2020 Jim Bennett

cadena hola = "Hola Xamarin en acción";

Este es un cambio de código de una línea en un archivo en código compartido. Si construye y ejecuta el
Ahora, las aplicaciones de Android e iOS verán que ambas tienen el nuevo texto que se muestra en el texto
caja y etiqueta, como en la figura 2.21.
Las aplicaciones tienen el mismo aspecto y funcionan igual. La única diferencia es la original.
valor de cadena que se muestra al inicio.

78 de 1189.
48 C APÍTULO 2 Hola MVVM: crear una aplicación multiplataforma simple usando MVVM

Figura 2.21 Ambas aplicaciones de muestra que muestran el nuevo texto, cambiaron cambiando solo una línea
de código

¿Entonces, cómo funciona todo esto? Veamos esta solución para ver cómo encaja en nuestras capas.
Esta aplicación tiene dos vistas, una en iOS y otra en Android, un modelo de vista en cross- compartido
código de plataforma y una cadena que actúa como modelo (figura 2.22).
Antes de que podamos entrar en más detalles sobre lo que está sucediendo aquí, hay mucho
Más sobre MVVM tenemos que discutir. En el próximo capítulo tomaremos esa inmersión más profunda
en MVVM, y una vez que haya visto con más profundidad cómo funciona MVVM, veremos
Más detalles en el código que acabamos de construir.

iOS Androide

C# C#
App
capa
C # (.NET Standard) App

C# C#

Primera vista Primera vista


Capa de interfaz de usuario Ver
UILabel Vista de texto
UITextField Editar texto

Enlace (desde el marco)

C # (.NET
Lógica de la interfaz de usuario FirstViewModel Ver
Estándar)
capa cadena Hola {get; set;} modelo

Figura 2.22 Nuestro código de IU está en


C # (.NET la capa de interfaz de usuario específica de la plataforma;
Negocio
Estándar) "Hola Xamarin Modelo nuestra clase principal con su cadena
capa lógica
en acción"
la propiedad está en la plataforma cruzada
capa de lógica de negocios.

Página 79
Resumen 49

Resumen
En este capítulo aprendiste que
▪ Varios patrones de diseño han evolucionado con el tiempo para ayudar a mejorar
UI aplicaciones. La última encarnación de estos, MVVM, es muy adecuada para
crear aplicaciones de Xamarin, ya que maximiza la cantidad de código multiplataforma en
nuestras aplicaciones
▪ Una aplicación Xamarin multiplataforma no es totalmente multiplataforma. En cambio, es una aplicación
donde todas las plataformas están escritas en el mismo lenguaje (C #) para que pueda compartir
Una gran parte de su código.
▪ El código multiplataforma está escrito en bibliotecas .NET Standard que proporcionan acceso a

https://translate.googleusercontent.com/translate_f 50/131
23/2/2020 Jim Bennett
Un subconjunto de .NET que funciona en todas las plataformas.
▪ El patrón MVVM consta de tres capas. Puedes escribir dos de estas capas,
el modelo y el modelo de vista, una vez dentro de una biblioteca .NET Standard y compartir
El código entre sus aplicaciones iOS y Android.

También aprendiste a
▪ Use una extensión en Visual Studio para crear una aplicación Xamarin multiplataforma, con
proyectos para iOS y Android, y un proyecto básico de biblioteca .NET Standard para
código compartido
▪ Ejecute estas aplicaciones dentro del simulador de iOS y el emulador de Android.

80

3
la vista-modelo-vista
modelo de diseño del modelo

MVVM—
Este capítulo cubre
▪ Una vista más detallada de lo que hay en el modelo, ver modelo,
vista y capas de unión
▪ Cómo un modelo de vista proporciona lógica de interfaz de usuario multiplataforma al
estado y comportamiento de modelado
▪ Uso de notificaciones de propiedades modificadas
▪ Usar comandos
▪ Cómo la capa de encuadernación pega la vista y las capas del modelo de vista
juntos
▪ Conversión de valor en el modelo de vista y convertidores de valor.
▪ Qué sucede en la capa de aplicación.
▪ Patrones de navegación para aplicaciones MVVM

https://translate.googleusercontent.com/translate_f 51/131
23/2/2020 Jim Bennett

50

www.allitebooks.com

Página 81
51

En el capítulo anterior vimos el MVVM


Patrón de diseño de la interfaz de usuario, antes de crear nuestra primera cruz Sqrt

aplicación de ejemplo de plataforma. Vamos a examinar eso


aplicación de ejemplo con mucho más detalle, pero primero necesitamos 400

para ver las capas en una aplicación MVVM en más


profundidad. Para hacer esto, tomaremos una calculadora de ejemplo √
aplicación (figura 3.1) y mira cómo escribiríamos esto 20

usando MVVM.
Para entender cómo construir esta aplicación, necesitamos Raíz cuadrada

mire cómo interactuará el usuario con la interfaz de usuario y


ver cómo esas interacciones se mueven hacia arriba y hacia abajo
a través de las capas de MVVM. La figura 3.2 muestra un
Resumen de alto nivel. Figura 3.1 Una raíz cuadrada simple
aplicación de calculadora que calcula el
raíz cuadrada de un número dado

1. La aplicación se inicia, 2. El usuario ingresa al 3. El usuario toca el cuadrado 4. El resultado de 20 es


creando el modelo, número 400 en un texto Botón de raíz, y esto calculado en el modelo,
ver, ver modelo, cuadro, y este valor es la acción se propaga y el valor se propaga
y vinculante. propagado a través de abajo a través de las capas retroceder a través de las capas
las capas hasta que termine al modelo, donde el hasta que se muestre en la interfaz de usuario
como un número en el modelo. Se calcula la raíz cuadrada. como texto en una etiqueta.

√ Sqrt Sqrt Sqrt


Raíz cuadrada

400 400 400

√ √ √
20

Raíz cuadrada Raíz cuadrada Raíz cuadrada

Ver

Unión

Ver modelo

Modelo

Figura 3.2 Una interacción típica del usuario con nuestra calculadora de raíz cuadrada

82
52 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

Al final de este capítulo, volveremos a visitar este diagrama de aplicación, separando cada capa y
viendo todas las interacciones que tienen lugar entre cada capa. Este capitulo es teorico
en lugar de practicar, pero es importante para entender cómo estructurar su aplicación para
Aproveche al máximo las capacidades multiplataforma que ofrece Xamarin. El código
Los ejemplos aquí son ejemplos simples y pseudocódigo, no partes de una aplicación totalmente funcional.
En el próximo capítulo tomaremos lo que aprenda aquí y lo usaremos para comprender y
construya sobre la aplicación de ejemplo que creó en el capítulo anterior.
Comencemos mirando cómo esta aplicación podría dividirse entre las diferentes capas.

3.1 La capa modelo


La capa modelo es una capa multiplataforma que representa sus datos, su lógica empresarial,
y su acceso a recursos externos como bases de datos o servicios web. El simple cal-
la aplicación Culator no necesita acceder a ningún recurso externo, pero si necesita persistir
datos a una base de datos o interactuar con servicios web, lo haría en la capa del modelo.
En nuestro ejemplo de calculadora, la capa del modelo contendría una calculadora de raíz cuadrada
clase que toma un número, calcula la raíz cuadrada y hace que el resultado esté disponible,
similar a la estructura que se muestra en la figura 3.3.
La siguiente lista muestra una posible implementación. La clase tiene un número

https://translate.googleusercontent.com/translate_f 52/131
23/2/2020 Jim Bennett
propiedad, Número , un método Sqrt que calcula la raíz cuadrada del número y un
Propiedad de resultado de solo lectura que almacena el resultado.

Listado 3.1 Una posible implementación de SquareRootCalculator

clase pública SquareRootCalculator


{
Número doble público {get; conjunto;}
resultado doble público {get; conjunto privado;

público vacío Sqrt ()


{
Resultado = Math.Sqrt (Número);
}
}

iOS Androide

C# C#
App
capa
C # (.NET Standard)

Capa de interfaz de usuario C# C# Ver

Enlace (desde el marco)

Lógica de la interfaz de usuario Ver


C # (.NET Standard)
capa modelo

C # (.NET
Negocio Estándar)
SquareRootCalculator Modelo Figura 3.3 La capa modelo
capa lógica
con las clases para el
aplicación de calculadora

Page 83
La capa de modelo de vista 53

La capa modelo es una capa: contiene una o más clases que trabajan juntas. Como tu
ver más adelante en este capítulo, generalmente tendrá una vista cuyo nombre tiene el sufijo Vista
para una pantalla (por ejemplo, SquareRootView ) y un modelo de vista para esa vista con un
nombre con sufijo ViewModel (como SquareRootViewModel ). Es normal suponer
que debe haber una clase de Modelo correspondiente que proporcione los datos y el negocio
lógica para ese modelo de vista, pero este no tiene que ser el caso. Si quieres escribir tu
codifique de esa manera, adelante, pero no sienta que tiene que hacerlo.
Hay muchas formas de construir la capa del modelo siguiendo muchos patrones diferentes
y prácticas (como enfoques orientados al dominio o centrados en datos). Como construyes
esta capa depende de usted, pero hay algunos principios fundamentales que debe seguir para hacer
esta capa la primera M de MVVM:
▪ El código debe ser multiplataforma. Una de las razones para usar este patrón es que
le permite reutilizar la mayor cantidad de código posible.
▪ El código debe ser comprobable. Otra razón clave para usar MVVM es la comprobabilidad.
La segregación de la interfaz de usuario de su lógica significa que puede probar esa lógica unitariamente, y
este mismo principio debería aplicarse aquí. Su capa de modelo debe ser comprobable
usando pruebas unitarias: sus clases deben estar bien escritas con responsabilidades únicas
para que las pruebas se puedan definir claramente.
Nuevamente, pensando en nuestra aplicación de calculadora, la clase SquareRootCalculator es
Muy fácil de probar por unidad. Podría escribir pruebas que establezcan diferentes valores para Número ,
llame a Sqrt y verifique la propiedad Resultado . Este es un ejemplo trivial, pero incluso en un
Necesitarás una aplicación más complicada para asegurarte de que sea comprobable. De esta manera puedes
asegúrese de que su modelo funcione sin tener que crear y ejecutar siempre su aplicación.
▪ El modelo debe representar datos y lógica empresarial a nivel de dominio, no a nivel de UI:
Este es un principio importante de la capa del modelo: debe representar su
datos y lógica a un nivel que tenga sentido para su dominio. Cualquier conversión de valor
de los datos en términos comerciales a términos de UI no deben realizarse en esta capa.
Pensando nuevamente en nuestra aplicación de calculadora, la interfaz de usuario controla para ingresar valores
y mostrarlos generalmente trata con valores de cadena . Las cuerdas no son buenas aquí como
necesita calcular usando números, por lo que el modelo siempre debe pensar en términos
de números Las otras capas pueden manejar cadenas y conversiones.

PRUEBAS DE LA UNIDAD La prueba de la unidad es un tema enorme, digno de un libro en sí mismo.


bien, así que no voy a entrar en muchos detalles al respecto aquí. Todo lo que estaré cubriendo
es cómo acercarse a escribir su aplicación usando MVVM para ayudarlo a escribir su
pruebas unitarias. Si quieres leer más sobre este tema, te recomiendo The Art of Unit
Pruebas , segunda edición, por Roy Osherove (Manning, 2013).

3.2 La capa de modelo de vista


La capa del modelo de vista (la VM al final de MVVM) es la capa lógica de la interfaz de usuario. Esta capa es
responsable de dos cosas:

https://translate.googleusercontent.com/translate_f 53/131
23/2/2020 Jim Bennett
84
54 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

▪ Conversión de valor: de los datos en la capa del modelo representados de manera que
tiene sentido para su dominio en la forma en que los datos se representan en la interfaz de usuario
▪ Lógica de la interfaz de usuario : como la lógica que determina cuándo mostrar datos y cuándo y cómo
navegar entre diferentes vistas

Hay algunos principios básicos detrás de un buen modelo de vista:


▪ Al igual que la capa del modelo, debe ser multiplataforma.
▪ Nuevamente, al igual que la capa del modelo, debe ser fácilmente comprobable usando pruebas unitarias. Usted quiere
tener una aplicación de la más alta calidad posible, para poder probar la lógica de la interfaz de usuario
El uso rápido y exhaustivo de las pruebas unitarias lo ayudará a lograr este objetivo.
▪ Debe ser enlazable. El enlace es el pegamento que conecta el modelo de vista al
vista, y el modelo de vista necesitará implementar características tales como propiedad
notificaciones modificadas que permiten que la capa de enlace esté al tanto de los cambios
que puede mantener la interfaz de usuario y ver el modelo sincronizado.
▪ Debe ser apátrida. El modelo de vista es una conversión de valor y una capa lógica. Sus
no un almacén de datos, por lo que su estado siempre debe provenir de la capa del modelo. Cuando el
La interfaz de usuario cambia el estado (como cuando se actualiza un cuadro de texto) el enlace le dice al
ver modelo que algo ha cambiado y que el modelo de vista es responsable
para actualizar el estado en el modelo.

El modelo de vista es la carne del patrón MVVM, y generalmente se asignará uno a uno
contra las diferentes pantallas o a diferentes secciones de cada vista. En nuestra calculadora
aplicación, queremos un modelo de vista que envuelva el modelo, llamado SquareRootViewModel (figura
3.4) Si tuviéramos una aplicación con varias pantallas, tal vez una para raíces cuadradas y otra para
raíces cúbicas, también tendríamos dos modelos de vista, SquareRootViewModel y CubeRoot-
ViewModel , cada uno accediendo a la capa del modelo. Porque nuestra capa modelo es una capa y
no se mapea uno a uno con modelos de vista, podríamos tener tanto raíz cuadrada como cubo
root en la misma clase de modelo, y ese modelo sería utilizado por ambos modelos de vista.

3.2.1 Estado y comportamiento

Cuando se considera una IU, realmente hay dos cosas en las que pensar: estado y comportamiento.
▪ Estado es la información que ve en la pantalla, ya sean datos reales, como texto y
números o una representación del estado de la aplicación, como la desactivación de botones
o errores de validación que se muestran alrededor de los cuadros de texto. Estado es una representación de
los datos en el modelo de una manera que se asigna a la interfaz de usuario, utilizando propiedades , al igual que el
propiedades que pondrías en una clase.
▪ Comportamiento son las acciones que ocurren cuando un usuario interactúa con la IU. La vista
modelo es la implementación de esto. El comportamiento se representa mediante comandos ,
objetos que encapsulan algún tipo de lógica, que se dispara al interactuar con
la interfaz de usuario de una manera que ejecuta el comando.

Piensa en conducir un auto. Estás conduciendo a cierta velocidad, como lo indica la velocidad
eter. Al presionar el acelerador vas más rápido; apretando el freno vas más lento.

Page 85
La capa de modelo de vista 55

iOS Androide

C# C#
App
capa
C # (.NET Standard)

Capa de interfaz de usuario C# C# Ver

Enlace (desde el marco)

C # (.NET
Lógica de la interfaz de usuario
Estándar) Ver
capa
SquareRootViewModel modelo

C # (.NET Figura 3.4 El modelo de vista


Negocio Estándar) clases para la aplicación de calculadora,
SquareRootCalculator Modelo
capa lógica
con un modelo de vista que envuelve
the SquareRootCalculator

El estado es la velocidad, representada en millas o kilómetros por hora. El auto disuade


mina su velocidad midiendo la velocidad de rotación del eje de transmisión y convirtiendo
este valor en la velocidad de un vehículo. En este caso, la medición de la velocidad del eje de transmisión es
expuesto al velocímetro como una representación de la velocidad del eje de transmisión pero es con-
vertido matemáticamente a la velocidad del vehículo.
El comportamiento es la capacidad de cambiar la velocidad presionando el acelerador o el freno.
Cuando presiona el acelerador, el motor deja entrar más combustible / aire, haciendo que
El motor va más rápido. Cuando presiona el freno, las ruedas se ralentizan mediante fricción.
La representación de cómo aumentar la velocidad es presionar el pedal del acelerador. los
La representación de cómo disminuir la velocidad es presionar el pedal del freno.

https://translate.googleusercontent.com/translate_f 54/131
23/2/2020 Jim Bennett
El velocímetro representa la velocidad del motor, y los pedales representan el
comportamiento de cambio de velocidad, todo de una manera amigable para el conductor. Esto es análogo a nuestro
Capas MVVM. El modelo es la mecánica del automóvil, y la vista es la velocidad.
ter y pedales. El modelo de vista representa la velocidad del vehículo y el comportamiento del cambio de velocidad.
ior al velocímetro y los pedales de una manera que sea consistente con la vista.
Si consideramos nuestra aplicación de raíz cuadrada, tenemos un número y la capacidad de tocar un
botón para calcular la raíz cuadrada y ver el resultado. El estado aquí es el número que
desea calcular la raíz cuadrada de, así como el resultado. El comportamiento es un comando.
que encapsula la lógica para calcular la raíz cuadrada. Al tocar el botón, usted
ordenar al modelo de vista que haga algo que haga este cálculo.
Probablemente suene un poco contradictorio decir que el modelo de vista representa el estado
y comportamiento después de decir que uno de los principios básicos es que debe ser apátrida.
Examinemos qué se entiende por ambas cosas.
El modelo de vista representa el estado de la interfaz de usuario en que todos los valores y la lógica que
definir los datos que se muestran en la interfaz de usuario provienen del estado del modelo de vista expuesto a
La capa de vista. Los valores en el cuadro de texto y la etiqueta provienen de las propiedades de la vista
modelo. La configuración que define si un control es visible u oculto proviene de

86
56 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

propiedades del modelo de vista. En este sentido, el modelo de vista proporciona una representación
del estado de la capa del modelo a la interfaz de usuario.
Sin embargo, como clase, el modelo de vista no debería tener estado, ya que obtiene su estado de
la capa del modelo y no debería aferrarse a este estado en sí. Los valores en el cuadro de texto
y la etiqueta se leen desde el modelo de vista, pero la fuente original es la capa del modelo (fig.
ure 3.5). En cualquier momento, debe poder recrear el modelo de vista a partir de los datos en
la capa del modelo, porque no almacenará ningún estado en sí mismo.

1. La encuadernación necesita unirse 4. El modelo de vista devuelve su


Ver
a una propiedad llamada "Resultado", representación del resultado a
entonces obtiene este valor del La capa de unión. La Unión
estado representado por el resultado Unión capa es independiente de donde el
propiedad en el modelo de vista. el valor vino originalmente;
Ver modelo solo le importa que vea un
Resultado
representación del estado en
2. El modelo de vista representa el El modelo de vista.
estado, pero el modelo contiene
el estado, por lo que la propiedad Resultado 3. El modelo contiene el actual
en la vista el modelo lee su valor Modelo estado y devuelve el valor
de Resultado de la propiedad en resultado doble público {get; set;} de su resultado propiedad a la
el modelo. Ver modelo.

Figura 3.5 El modelo de vista es una representación del estado que se muestra en el modelo.

El estado real está en la capa del modelo, y el modelo de vista convierte ese estado en estado
eso es apropiado para la capa de vista. El modelo de vista representa el estado, pero el modelo
contiene el estado Al tener el modelo de vista como una representación, puede devolver el
estado directamente o realizar conversiones de valor en el estado antes de devolverlo al
capa de unión.
P ROPERIDADES Y NOTIFICACIONES CAMBIADAS
En su forma más simple, una propiedad de un modelo de vista es igual a cualquier otra propiedad que usted
puede haber usado en el código C #. Tiene un getter y un setter: métodos que devuelven algunos datos.
o establecer los datos. Internamente en estos métodos, podría devolver o actualizar valores, o
Podría tener algo de lógica. En su forma más simple, una propiedad puede obtener y establecer un valor en
modelo, como se muestra aquí.

Listado 3.2 Propiedad de paso que obtiene y establece el primer valor numérico en el modelo

El modelo de vista SquareRootViewModel El modelo de vista tiene una instancia de


clase. La convención es nombrar vista El modelo almacenado como un campo privado.
modelos con el sufijo "ViewModel".
El modelo de vista expone el número.
clase pública SquareRootViewModel para ser utilizado en el cálculo a través de
{ la propiedad Number.
SquareRootCalculator sqrtCalc;
El captador para la propiedad Number es un simple
Número doble público paso a través: solo devuelve el valor de
{ propiedad en el modelo subyacente.
get {return sqrtCalc.Number; }

Page 87
La capa de modelo de vista 57

set {sqrtCalc.Number = value; }


El setter también es un paso simple,
} establecer el valor en el modelo subyacente.
Resultado doble público

https://translate.googleusercontent.com/translate_f 55/131
23/2/2020 Jim Bennett
{ El resultado también es un traspaso,
get {return sqrtCalc.Result; } pero es de solo lectura en el modelo
} es solo un getter, no un setter.
}

Hasta ahora, muy simple. De hecho, probablemente se esté preguntando por qué nos molestamos con un modelo de vista
en absoluto si solo llama directamente al modelo. La razón para usar un modelo de vista es porque
los modelos de vista admiten notificaciones de cambio de propiedad (la aparición de un evento para contarle a cualquiera)
alguien interesado en que una propiedad haya cambiado. ¿Recuerdas la capa de unión? Esta
mantiene la UI sincronizada con los datos subyacentes, y parte de mantener esto sincronizado es
consciente de cuándo cambian las cosas. La Figura 3.6 es un resumen de la unión, destacando esto.

Sqrt
La propiedad Text del TextBox está vinculada a una propiedad
llamado "Número" en el modelo de vista. El aspecto vinculante
arriba la propiedad "Número" en el modelo de vista y encuentra
400 usando la reflexión

√ El enlace escucha las actualizaciones de la propiedad Text de


TextBox (generalmente a través de un evento modificado por texto generado por
20 el cuadro de texto). Cuando el usuario cambia el texto, el enlace
actualiza la propiedad Number en el modelo de vista.

Raíz cuadrada
El enlace también escucha las actualizaciones de Number. Cuando
la propiedad cambia, actualiza la propiedad Text del
TextBox en la interfaz de usuario.

Caja de texto Ver modelo


Unión
Texto Número

Figura 3.6 El enlace escucha los cambios en el modelo de vista y actualiza la vista en consecuencia.

La forma en que la capa de enlace hace esto es a través de notificaciones de propiedades modificadas. Estas
son eventos generados por el modelo de vista que le dice a cualquiera que esté interesado que una propiedad tiene
cambiado En nuestro caso, la capa de enlace está interesada, por lo que escucha estas notificaciones.
Cuando obtenga uno, leerá el nuevo valor de la propiedad y actualizará la IU para que coincida.
Sin embargo, la forma estándar de implementar notificaciones de cambio de propiedad en C #
una interfaz llamada INotifyPropertyChanged . Esta interfaz ha existido desde
.NET 2.0 (hace más de una década), y solo tiene un miembro, un evento llamado Property-
Modificado , que utiliza el delegado de controlador de eventos estándar, pasando un objeto que
define el remitente y algunos argumentos de eventos. Estos argumentos son de tipo
PropertyChangedEventArgs , y este tipo solo tiene un miembro de nota: Property-
Nombre , el nombre de la propiedad que ha cambiado como una cadena . La siguiente lista
muestra esta interfaz

Page 88
58 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

Listado 3.3 La interfaz INotifyPropertyChanged

interfaz pública INotifyPropertyChanged


{
evento PropertyChangedEventHandler PropertyChanged;
}

Este evento no incluye el valor que ha cambiado, solo el nombre. La capa de unión
se suscribirá a este evento, y cuando se genere, obtendrá el nombre de la propiedad
desde los argumentos del evento, busque el control (o controles) de la interfaz de usuario que está vinculado a una propiedad de
ese nombre, lea el nuevo valor del modelo de vista y actualice la IU.

NOTIFICANDO QUE TODAS LAS PROPIEDADES HAN CAMBIADO Por convención, si utiliza un
cadena vacía o nula como el nombre de la propiedad en el evento argumenta cuando se genera este
evento, le dice a la capa de enlace que todo ha cambiado, por lo que debería
releer todos los valores y actualizar la IU. Sin embargo, ten cuidado; no todos los MVVM
El marco obedecerá esta convención.

Podemos actualizar el ejemplo del modelo de vista para implementar esto. Cuando el numero
cambios, o el resultado de los cambios de raíz cuadrada, debemos notificar el enlace de este
cambiar a través de una notificación de cambio de propiedad. Una cosa a tener en cuenta aquí es que su punto de vista
el modelo solo debe notificar si algo ha cambiado realmente, si el valor no ha cambiado
cambiado, el evento no se debe generar.
Agreguemos un método Sqrt para nuestra vista para ilustrar esto.

Listado 3.4 Agregar notificaciones de propiedades modificadas a nuestro modelo de vista

El modelo de vista necesita implementarse Llega el evento PropertyChanged


INotifyPropertyChanged. desde INotifyPropertyChanged
interfaz.

clase pública SquareRootViewModel: INotifyPropertyChanged


{
evento público PropertyChangedEventHandler PropertyChanged;

nulo RaisePropertyChanged (nombre de cadena)


{
PropertyChanged? .Invoke (esto,
nuevo PropertyChangedEventArgs (nombre));

https://translate.googleusercontent.com/translate_f 56/131
23/2/2020 Jim Bennett
}

RaisePropertyChanged
El método es un método auxiliar para
El evento se genera mediante evento
elevar la propiedad cambiada
argumentos que contienen el nombre del
evento para una propiedad dada.
propiedad que ha cambiado.

Page 89
La capa de modelo de vista 59

Número doble público


{
get {return sqrtCalc.Number; }
conjunto
{
if (sqrtCalc.Number == value) return;
sqrtCalc.Number = value;
RaisePropertyChanged ("Número");
Después de la propiedad Number
}
cambios, una propiedad
}
Se genera un evento modificado.
público vacío Sqrt ()
{
sqrtCalc.Sqrt ();
RaisePropertyChanged ("Resultado");
}
Después del método Sqrt en
...
el modelo se llama, el
}
La propiedad del resultado se actualiza
entonces se levanta el evento.
Cuando se establece la propiedad Number, el nuevo valor
se compara con el anterior, y si el valor
en realidad no ha cambiado, no pasa nada: no
actualización y sin notificación de cambio de propiedad.

Simplificando RaisePropertyChanged usando un atributo


C # define un atributo llamado CallerMemberName que puede establecer en un parámetro de cadena
eter de un método, y le dice al compilador que use el nombre del método de llamada o
propiedad como el valor para este parámetro. Esto significa que puede definir su propiedad
método cambiado de la siguiente manera:

nulo RaisePropertyChanged ([CallerMemberName] string name = null)

Luego puede llamarlo usando RaisePropertyChanged () desde el conjunto de propiedades-


ter, sin pasar ningún valor explícito de nombre al método. El nombre del prop-
Cada una de estas llamadas se establecerá automáticamente como parámetro de nombre. Por ejemplo,
si llama a esto desde dentro del establecedor de la propiedad Number, el valor del nombre
el parámetro será "Número". Una serie de marcos MVVM, incluidos MvvmCross,
use esto para sus métodos de cambio de propiedad de aumento.

Las notificaciones de cambio de propiedad son la forma de decirle a la capa de enlace que algo
ha cambiado. Puede notificar sobre cualquier propiedad en cualquier momento, no tiene que notificar
sobre el cambio de propiedad. Por ejemplo, si su modelo de vista tenía dos
vínculos para el nombre y apellido de una persona, y una propiedad que refleje su nombre completo
como una concatenación de los nombres y apellidos, querría cualquier cambio en el
nombre o apellido para generar una notificación de cambio de propiedad para el nombre completo, como
se muestra en el siguiente listado.

Página 90
60 60 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

Listado 3.5 Las notificaciones de cambio de propiedad se pueden generar para cualquier propiedad en cualquier momento

Nombre de cadena pública La propiedad Nombre es


{ dependiente de los valores de
get {return FirstName + "" + LastName; } Nombre y apellido.
}

Nombre de cadena pública


{
get {return model.FirstName; }
conjunto
{ Debido a esta dependencia,
if (model.FirstName == value) return; cuando FirstName cambia, se
model.FirstName = value; plantea una propiedad modificada

https://translate.googleusercontent.com/translate_f 57/131
23/2/2020 Jim Bennett
RaisePropertyChanged ("Nombre"); notificación para sí mismo y para
RaisePropertyChanged ("Nombre"); La propiedad Nombre.
}
}

C COLECCIONES Y COLECCIONES - NOTIFICACIONES CAMBIADAS


Además de usar propiedades individuales, hay una forma estándar en C # de notificar
la capa de enlace que los elementos de una colección han cambiado: usando una interfaz similar
llamado INotifyCollectionChanged . Esto generalmente se usa con controles de lista (UI wid-
consigue que muestre una lista o tabla de datos. Al igual que con INotifyPropertyChanged , el enlace-
La capa ing se suscribe a un evento, y cuando recibe este evento, le dirá a la lista
control para recargar los cambios.
A diferencia de INotifyPropertyChanged , esta no es una interfaz que el modelo de vista
define; en cambio, esto está en el nivel de propiedad. El modelo de vista expondrá una propiedad de
un tipo que implementa INotifyCollectionChanged , y cuando la capa de enlace
enlaza esta propiedad a una propiedad correspondiente en el control de lista, también sub-
escriba al evento en esa propiedad.
Un ejemplo de esto, con una aplicación que muestra una lista de nombres, se muestra en la figura 3.7.
Esta interfaz solo contiene un miembro, un evento llamado CollectionChanged . Esta
utiliza el delegado de controlador de eventos estándar con argumentos de eventos de tipo NotifyCollection-
ChangedEventArgs . La siguiente lista muestra esta interfaz.

Listado 3.6 La interfaz INotifyCollectionChanged

interfaz pública INotifyCollectionChanged


{
evento NotifyCollectionChangedEventHandler CollectionChanged;
}

Estos argumentos de eventos contienen una serie de propiedades que le permiten describir los cambios.
que se han hecho a la colección. Esto, a su vez, permite que el control de la lista enlazada
responda apropiadamente si es posible.
Sin embargo, para la mayoría de los casos de uso, no necesita preocuparse demasiado por esto porque
hay una buena colección útil que ya forma parte de .NET Framework que tiene
dles todo esto para usted: ObservableCollection <T> . La colección se deriva de la

Page 91
La capa de modelo de vista 61

Ver
La propiedad ItemsSource de la Lista está vinculada a una propiedad
Nombres: llamados "Elementos" en el modelo de vista. El enlace mira hacia arriba
Propiedad "Elementos" en el modelo de vista y lo encuentra.
Jim

Beto El enlace también escucha las actualizaciones de la lista de elementos. Cuando


Alison
la colección cambia, actualiza la propiedad ItemSource
de la Lista en la IU.
Kim

Lista Ver modelo


Unión
público IEnumerable
Número
ItemSource {get; set;}

Figura 3.7 Las colecciones se pueden vincular a los controles de la lista, y cuando la colección cambia, la lista
Se actualiza el control de la interfaz de usuario.

Lista genérica <T> e implementa INotifyCollectionChanged . Cuando realizas


cualquier acción que cambie la lista, generará el evento con los argumentos correctos.
Cuando cambia la ObservableCollection subyacente (como cuando un elemento es
agregado), el evento se genera y el enlace lo detecta y le dice al control de la lista
para actualizar y mostrar los cambios. Esto se muestra en la figura 3.8.
Sin embargo, tenga en cuenta que ObservableCollection elevará el valor de CollectionChanged
evento para todos los cambios, por lo que si está agregando miles de elementos, la interfaz de usuario se actualizará
arenas de veces, que pueden ralentizar o incluso bloquear su interfaz de usuario. Probablemente sea mejor en este caso
para crear una nueva colección, agréguele todos los valores y luego configure su propiedad

Ver
Cuando se agrega un nuevo elemento a los Elementos observables
Nombres: colección (en este caso "Gary"), la ColecciónCambiada
Jim
El evento se plantea.

Beto
El enlace detecta este evento y le dice al control List
Alison
actualizarse para mostrar la nueva entrada. Gary aparece entonces
Kim al final de la lista.
Gary

Lista Colección modificada Ver modelo

Se agrega un nuevo elemento a la lista Items.Add ("Gary");

https://translate.googleusercontent.com/translate_f 58/131
23/2/2020 Jim Bennett

Figura 3.8 Cuando se actualiza una colección observable, se genera un evento y el enlace detecta
esto y le dice a la interfaz de usuario que se actualice.

Página 92
62 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

nueva colección, lo que lleva a una única actualización de la interfaz de usuario. La siguiente lista muestra un examen
ple de esto.

Listado 3.7 Crear una nueva colección y actualizar la propiedad

public ObservableCollection <string> Nombres {get; conjunto privado;

void AddLotsToTheCollection (IEnumerable <string> lotsOfNames)


{
var newCollection = new ObservableCollection <string> (Nombres);

foreach (nombre de var en lotsOfNames)


newCollection.Add (nombre);

Nombres = newCollection; La propiedad pública para el


RaisePropertyChanged ("Nombres"); la colección observable se actualiza
} a la colección recién creada.

Una nueva colección observable es


Una propiedad cambiada
creado, copiando los valores de
notificación se plantea para decirle al
La colección existente. UI para usar la nueva colección.

OTRAS IMPLEMENTACIONES DE ObservableCollection PUEDEN HACER ESTE AÚN MÁS FÁCIL


Hay varias implementaciones de ObservableCollection disponibles.
en varios proyectos de código abierto que brindan un mejor soporte para operaciones masivas
bloqueando el evento de cambio de colección hasta que se completen todas las operaciones.
Una de esas implementaciones de MvvmCross es MvxObservableCollection ,
que tiene un método AddRange que suprime el evento de cambio de colección,
agrega todos los elementos pasados al método y luego levanta la colección modificada
evento. Esta colección también proporciona métodos para eliminaciones y reemplazos masivos.
ments y para suprimir el evento de cambio de colección mientras realiza
operaciones personalizadas

C OMANDAS
Las propiedades del modelo de vista definen su estado, por lo que lo siguiente a considerar es cómo
El comportamiento está definido. La forma estándar de definir el comportamiento en MVVM está utilizando la com-
patrón de mand . En este patrón, todo lo necesario para realizar una acción está encapsulado
en un objeto, y le dice a este objeto que desea que realice su acción en un determinado
tiempo, dándole cualquier información adicional que necesita sobre el tiempo particular que se ejecuta.
Piensa en un genio: tu deseo es su orden. Le dices al genio que quieres un café
tarifa, y obedece tu orden usando su magia, y puf, aparece un café, como se muestra
en la figura 3.9.
Puede pensar en el patrón de comando de la misma manera. El comando es un objeto.
que encapsula la capacidad de realizar una acción, como un genio que encapsula
la capacidad de conceder tu deseo Ejecutas el comando con un parámetro opcional,
ordenando al genio que te traiga café. El comando luego realiza el
acción: el genio te trae café.
En el mundo C #, ICommand es la interfaz para un objeto que implementa este comando
patrón de mand. Tiene un método que puede invocar para ejecutar el comando con un parámetro
eter, un método al que puede llamar para ver si puede ejecutar el comando con un parámetro,

Página 93
La capa de modelo de vista 63

yo ordeno
Tu deseo es
tu para darme
mi comando
café

Figura 3.9 Al mando de un genio para traer


tu cafe Hubiera sido eterno
riqueza, pero el café era más fácil de extraer.

y un evento que se genera cuando su capacidad para ejecutar el comando cambia como
se muestra en el siguiente listado.

Listado 3.8 La interfaz ICommand

interfaz pública ICommand


{
Ejecutar vacío (parámetro de objeto);

https://translate.googleusercontent.com/translate_f 59/131
23/2/2020 Jim Bennett
bool CanExecute (parámetro de objeto);
evento EventHandler CanExecuteChanged;
}

Como se muestra en la figura 3.10, puede pensar en Ejecutar como un método que ordena
genio para conceder su deseo, y el parámetro como lo que desea. Tradicionalmente, un
genie solo concederá tres deseos, por lo que la figura 3.11 muestra que CanExecute regresará
es cierto mientras le quedan deseos, pero después de que su tercer deseo sea falso . los
El evento CanExecuteChanged es como el genio que te dice después de tu tercer deseo que has
quedarse sin deseos (y desaparecer en una nube de humo de vuelta a la lámpara).

Cheques genio
cuántos Tu deseo es
Ejecutar ( ) Menos de 3
desea que hayas mi comando
ya tenía

Si se concede un deseo,
3
el genio vuelve a comprobar
cuantos deseos
ya has tenido

Lo siento Después de 3 deseos, el


por deseos CanExecuteChanged El genio desaparece
3

de vuelta a su lámpara

Figura 3.10 Nuestro genio es como la interfaz ICommand : podemos pedir un deseo ( Ejecutar ) y ver cuándo hemos corrido
fuera de los deseos ( CanExecuteChanged ).

Page 94
64 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

Cheques genio
CanExecute ( ) cuantos deseos Menos de 3 cierto
ya has tenido

3 falso

Figura 3.11 También podemos preguntarle al genio si podemos tener más deseos ( CanExecute ).

El comando se expone como una propiedad en el modelo de vista, y la capa de enlace


tener una forma de conectar el comando a un widget en la interfaz de usuario.
El caso de uso clásico es con un botón. Los botones generalmente tienen un evento de clic o similar
evento que se ejecuta cuando se toca el botón. Cuando un botón está vinculado a un comando,
el evento click ejecutará el comando. El estado habilitado del botón también
estar vinculado al método CanExecute , por lo que si CanExecute devuelve verdadero , el botón es
habilitado, y si devuelve falso , el botón está deshabilitado. Esto se evaluaría cuando
el botón se enlaza primero y cada vez que el comando levanta CanExecuteChanged
evento. Esto se muestra en la figura 3.12.
En nuestra aplicación de calculadora, el botón de raíz cuadrada estaría vinculado a un comando
que, cuando se ejecuta, llama al método Sqrt en el modelo. Si no ha ingresado un
número en el cuadro de texto, no se puede calcular una raíz cuadrada, por lo que en este caso el Can-
Ejecutar devolverá falso y el botón se deshabilitará. Una vez que ingrese el texto, el
CanExecuteChanged se generará para indicarle al enlace que reevalúe CanExecute y
habilitar el botón

Sqrt
El evento Click del botón está vinculado a una propiedad
llamado "SqrtCommand" en el modelo de vista. La Unión
busca la propiedad "SqrtCommand" en la vista
400 modelo y lo encuentra.

√ El enlace escucha el evento Click del botón.


Cuando esto se plantea, el método Ejecutar en el
20 Se llama al comando en el modelo de vista.

La propiedad Enabled del botón se establece en función de


Raíz cuadrada
El valor de retorno de CanExecute del comando. Si
el comando genera el evento CanExecuteChanged,
Esto se vuelve a evaluar.

Botón Ver modelo

evento público EventHandler Haga clic en {get;} Unión public ICommand SqrtCommand {get;}
public bool Enabled {get;}

Figura 3.12 Los eventos como los clics en los botones pueden vincularse a comandos, y estos comandos son
ejecutado cuando se genera el evento.

https://translate.googleusercontent.com/translate_f 60/131
23/2/2020 Jim Bennett

Page 95
La capa de modelo de vista sesenta y cinco

Los comandos no devuelven un resultado, simplemente se ejecutan y regresan una vez que han terminado. los
La forma de devolver un resultado, si es necesario, es haciendo cambios en el estado de la vista
modelar y generar un evento de cambio de propiedad. Algunos comandos no necesitan actualizar un
estado porque no hacen nada que requiera comentarios sobre la interfaz de usuario actual. Com-
Mands que necesitan actualizarse, como guardar datos e indicar que los datos tienen
guardado, lo hará actualizando una propiedad que hace que la IU cambie.
Por lo general, no necesita mucha lógica sofisticada con un comando: solo cree un comando
objetar y darle un método para que se ejecute cuando se ejecute. Desafortunadamente (y algo
sorprendentemente) no hay una implementación predeterminada de ICommand integrada en .NET
Marco que hace esto. Afortunadamente, hay muchas implementaciones de ejemplo
alrededor de Internet y otros están integrados en los diversos marcos MVVM. Estas
los comandos generalmente toman una acción que proporciona el método para ejecutarse en la ejecución,
y opcionalmente un predicado (un método que devuelve un booleano) para usar para el imple-
mentación de CanExecute . También proporcionan un método al que puede llamar para elevar el can-
Evento ExecuteChanged .
En nuestro modelo de vista de calculadora, podemos cambiar el método Sqrt que se muestra en el listado 3.4
a un comando, de la siguiente manera.

Listado 3.9 Agregar un comando al modelo de vista

clase pública SquareRootViewModel: INotifyPropertyChanged


{
...
public ICommand SqrtCommand {get; conjunto privado; El método Sqrt ha sido
public SquareRootViewModel ()
eliminado, y una nueva propiedad
{
de tipo ICommand ha sido
agregado, llamado SqrtCommand.
SqrtCommand = nuevo MvxCommand (o =>
{
Crea una nueva instancia.
sqrtCalc.Sqrt ();
del comando
RaisePropertyChanged ("Resultado");
});
}
}

En el constructor para el modelo de vista, SqrtCommand se establece en una nueva instancia de


MvxCommand , la clase de comando de MvvmCross que toma una Acción <objeto> para
ejecutar ( Ejecutar toma un objeto como parámetro, por lo que la acción debe tener un
parámetro de objeto ). La acción se invoca cuando se ejecuta el comando, y en este
ejemplo, la acción llama a Sqrt en el modelo y genera un cambio de propiedad para indicar
El resultado ha cambiado.

3.2.2 Conversión de valor


El modelo contiene datos de una manera relevante para el dominio o la lógica empresarial; el
La interfaz de usuario maneja los datos en un formato que puede funcionar con los widgets en la pantalla. Algunos de los
vez estos formatos serán los mismos, pero otras veces no coincidirán.

Page 96
66 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

Cuando no coinciden, el modelo de vista deberá convertir el estado del modelo.


a un estado que la UI puede usar. El modelo de vista representará el estado del modelo.
utilizando los valores convertidos. Del mismo modo, si la interfaz de usuario se actualiza, esto debe reflejarse en
actualizar el estado representado por el modelo de vista. Esto significa establecer un valor usando
datos en el formato relevante para la interfaz de usuario y luego convertirlos al formato utilizado por
modelo. Es el modelo de vista el responsable de esta conversión de valor.
Como probablemente haya notado en nuestra calculadora de raíz cuadrada, el modelo se ocupa de num-
bers como dobles. Esta es la capa empresarial, por lo que los dobles están bien. IU, por otro lado,
No suelen negociar en dobles. Cuadros de texto como el usado para ingresar el número
generalmente se manejan en cadenas, y también lo hacen etiquetas como la que estamos usando para mostrar el resultado.
Aquí es donde entra el modelo de vista: parte de su trabajo es la conversión de valor del
capa modelo a la capa UI. En este caso, debería ser responsable de la conversión de
cadenas en la interfaz de usuario a números en el modelo y viceversa.
Veamos cómo debería funcionar el código de clase del modelo de vista.

Listado 3.10 Conversión de valor de manejo del modelo (dobles) a UI (cadenas)

clase pública SquareRootViewModel


{ La propiedad Number en
El modelo de vista es una cadena. Para devolver una cadena, el
...
Número de cadena pública getter llama a ToString ()
{ en el doble valor
del modelo
get {return sqrtCalc.Number.ToString (); }
conjunto
{
if (value == Number) return;
Compara el valor con el
sqrtCalc.Number = double.Parse (valor);
valor existente usando la propiedad
RaisePropertyChanged ("Número"); en el modelo de vista en lugar de

https://translate.googleusercontent.com/translate_f 61/131
23/2/2020 Jim Bennett
} propiedad en el modelo. los
} el valor es una cadena, por lo que debe
compáralo con una cuerda
Cadena pública Resultado
del doble en el modelo.
{
get {return sqrtCalc.Result.ToString (); } De nuevo, para devolver un
} encadenar el modelo de vista
} llama a ToString () en el
valor del modelo.
Para establecer un doble en el modelo, el colocador analiza la cadena
en un doble. Esto podría fallar, así que en el mundo real
debe asegurarse de que el valor de la cadena siempre sea un número válido:
la mayoría de los cuadros de texto de la IU pueden limitar los caracteres que el usuario puede
ingrese a números y puntos decimales.

VER MODELOS SON RESPONSABLES DE LA CONVERSIÓN DE VALOR Las capas sobre el


ver el modelo pensar en términos de la interfaz de usuario, y las capas siguientes piensan en términos de
La lógica y el dominio del negocio. El modelo de vista es responsable de convertir
de uno a otro a medida que los datos pasan a través de esta capa.

La capa del modelo tiene datos como dobles. La capa de modelo de vista convierte estos valores en
cadenas y representa el estado de la capa del modelo a través de las propiedades de cadena. Esta

Page 97
La capa de modelo de vista 67

El estado está en el formato correcto para la capa de interfaz de usuario, por lo que la capa de enlace puede establecer el texto en el
La interfaz de usuario controla estos valores de cadena. Una vez que se actualiza un valor de cadena en la interfaz de usuario, el enlace
La capa ing actualiza la representación de cadena del número en el modelo de vista, que
convierte el valor a un doble y actualiza los datos en el modelo.
Hay momentos en los que es posible que desee una conversión de valor específica de plataforma
que la conversión multiplataforma en un modelo de vista, y puede hacerlo utilizando un valor de con-
verter Veremos esto más adelante en el capítulo.

3.2.3 Testabilidad
Al igual que la capa de modelo, la capa de modelo de vista debe construirse teniendo en cuenta la capacidad de prueba.
Ver modelos no solo proporciona lógica multiplataforma, sino que, cuando están bien construidos, puede
escriba pruebas unitarias para verificar que su lógica sea correcta: una base de código para esta lógica, un conjunto
de pruebas, un lugar para encontrar y corregir errores. Esta es una de las principales razones detrás de la
invención original de MVVM: puede escribir pruebas unitarias contra su lógica de UI. Es muy
fácil de hacer gracias a la forma en que los modelos de vista encapsulan el estado y el comportamiento. Puedes probar
interacciones del usuario con la interfaz de usuario escribiendo código de prueba que replica la forma en que se vincula
actualizaría el modelo de vista.
Por ejemplo, para probar que un usuario escribe en un cuadro de texto, en realidad no necesita un texto
caja. En su lugar, puede escribir código que actúe como la capa de enlace y establezca el valor de
la propiedad en el modelo de vista que estaría vinculada al cuadro de texto. Para probar actualizaciones
llegando a la interfaz de usuario desde el modelo de vista, solo necesita escuchar los cambios de propiedad o
eventos de cambio de colección, y cuando suceden, verifique que la propiedad o la colección
ción tiene el valor correcto. Para probar que un usuario hace clic en un botón, solo necesita ejecutar el
ordenar y verificar lo que sucede.
Al crear sus modelos de vista, siempre debe pensar en las pruebas unitarias. Tu
los modelos de vista deben estar bien desacoplados y utilizar técnicas como la interfaz sobre la implementación
mentación, lo mismo que para los modelos. También vale la pena ver cuál es su marco MVVM
ofrece ayudarlo con esto. Por ejemplo, algunos marcos proporcionan un mensajero para
permitir que sus modelos de vista se comuniquen indirectamente con otros modelos de vista (u otros
clases en su aplicación) sin tener que ser conscientes el uno del otro.
Para mejorar la capacidad de prueba del modelo de vista SquareRootCalculator , debemos
desacoplarlo del modelo exponiendo una interfaz en el modelo y pasando un
instancia de esa interfaz cuando el modelo de vista se construye dentro de nuestra aplicación. A partir de una
prueba unitaria, podemos crear un modelo simulado que implemente esta interfaz y luego usar
esto cuando construimos el modelo de vista. De esta manera tenemos control completo sobre qué
El modelo lo hará en la prueba.
Como se mencionó anteriormente, las pruebas unitarias son un gran tema, y la burla es un importante
Parte de ello. Está fuera del alcance de este libro, pero si siempre construyes tu modelo y
ver el código de capa del modelo para preferir la interfaz a la implementación, estará bien configurado para
examen de la unidad.

98
68 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

3,3 La capa de vista


En pocas palabras, la capa de vista es la interfaz de usuario. Todo lo que tiene que ser específico de la plataforma porque

https://translate.googleusercontent.com/translate_f 62/131
23/2/2020 Jim Bennett
se trata de widgets de IU está en la capa de vista. Esta capa debe ser lo más delgada posible y
solo contiene código para definir qué widgets se necesitan en la pantalla y los valores de cualquiera de
sus propiedades que no cambiarán según la lógica dentro del modelo de vista. Cuando estas
construyendo su vista, si se encuentra agregando alguna lógica, muévala al modelo de vista.
Pensando en nuestro ejemplo de calculadora, necesitaríamos crear dos vistas llamadas
SquareRootView , uno en la aplicación iOS y otro en Android. Este nombre está en custodia
Con la convención de la vista y el modelo de vista que tienen el mismo nombre con una diferencia
sufijo diferente, como se muestra en la figura 3.13.

iOS Androide

C# C#
App
capa
C # (.NET Standard)

Storyboard (XML) Diseño (XML)

Capa de interfaz de usuario C# C# Ver

SquareRootView SquareRootView

Enlace (desde el marco)

C # (.NET
Lógica de la interfaz de usuario
Estándar) Ver
SquareRootViewModel
capa modelo

C # (.NET
Negocio Estándar)
SquareRootCalculator Modelo Figura 3.13 La capa de vista es
capa lógica
no multiplataforma por lo que las vistas
tiene que ser creado dos veces.

Como esta capa no es multiplataforma, puede agregar todas las bondades de IU que desee en
esta capa: bonitos widgets, animaciones, efectos y todo lo que quieras que sea
específico para la plataforma para hacer que su interfaz de usuario se vea increíble. Solo recuerda eso porque
esta capa no es multiplataforma, todo debe escribirse dos veces, una para iOS y
una vez para Android, por lo que todo lo que se puede compartir (como la lógica) se debe compartir en
la capa de modelo de vista.
Tanto en iOS como en Android, hay dos partes en cualquier interfaz de usuario:
▪ Un archivo de diseño: contiene detalles de los widgets definidos en XML y puede usarse
con un diseñador visual Android llama a estos recursos de diseño; iOS tiene dos tipos de
estos, guiones gráficos y archivos XIB.
▪ Un archivo de código subyacente: proporciona la lógica que necesita la interfaz de usuario y define su ciclo de vida.
(como cuando se muestra la vista y cuando está oculta). En Android esto es
llamado una actividad ; en iOS este es un controlador de vista .

Page 99
Unión 69

Examinaremos estos archivos de diseño y código subyacente con más detalle en los capítulos 9 a
12 cuando analizamos la creación de interfaces de usuario para iOS y Android.
No hay mucho más que agregar sobre la capa de vista en términos de MVVM. La mayoría de
La magia de MVVM está en la capa de modelo de vista, por lo que lo único que hay que tener en cuenta aquí es qué
puede poner en la capa de modelo de vista y lo que tiene que estar en la capa de vista. Como un buen
Como regla general, desea hacer todo lo posible en el archivo de diseño y tan poco como sea posible.
Sible en el código subyacente. Si agrega código que no puede estar en el archivo de diseño para qué-
Por alguna razón, debe considerar si es la lógica genérica la que debería estar en la vista
modelo (y, por lo tanto, compartido entre plataformas) o si es específico de la plataforma y debe
estar en la capa de vista. Por ejemplo, si está mostrando u ocultando una etiqueta basada en
valor de una propiedad en el modelo de vista, la lógica para esto también debe estar en la vista
modelo. Si, por otro lado, está eligiendo cuál de un conjunto de
maciones que usará en función de una propiedad en el modelo de vista, esta lógica iría en el
capa de vista, aunque idealmente en una clase independiente y autónoma que podría ser probada por unidad.

3.4 Unión
La vinculación es la magia que une la vista y el modelo de vista en una forma holgada
camino pled. Es responsable de conectar las propiedades en la vista a las propiedades en el
ver el modelo y mantenerlos sincronizados, y para conectar eventos en la vista para
Mands en el modelo de vista para que estos comandos se ejecuten cuando el usuario interactúa
con la interfaz de usuario Al vincular, vincula una propiedad con nombre en la vista a un nombre
propiedad en el modelo de vista, y detrás del escenario el marco vinculante encontrará
las propiedades reales con los nombres de pila y conectarlos, configurando la vista en
hacer coincidir el valor en el modelo de vista y monitorear los cambios para que pueda mantener estos
valores sincronizados.
No hay nada en .NET Framework que ayude a unir todo. En lugar,
tienes que escribir la lógica tú mismo o usar un marco como MvvmCross,
MVVM Light, o Caliburn.Micro para hacerlo.
Hay un par de conceptos vinculantes a tener en cuenta: cuál es el origen y el destino
son, y cuál es el modo de enlace. También debe tener en cuenta que el enlace no es realmente
multiplataforma, por lo que puede ayudar si necesita enlazar propiedades cuyos tipos no son compatibles
portado en su código multiplataforma.

https://translate.googleusercontent.com/translate_f 63/131
23/2/2020 Jim Bennett

3.4.1 Fuente y destino

Cuando vincula una vista a un modelo de vista, conecta un objetivo a una fuente:
▪ La fuente es la fuente de datos original (el modelo de vista).
▪ El objetivo es el objetivo original de los datos (la vista).

Es fácil ver cómo estas definiciones pueden ser confusas, para un cuadro de entrada de texto en un nuevo
pantalla del usuario, la "fuente" de los datos podría considerarse lo que el usuario ingresa, pero
desde una perspectiva vinculante, la fuente siempre es el modelo de vista y el objetivo siempre es
la vista.

Página 100
70 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

A menudo escuchará el término fuente vinculante mencionado, y esto se refiere a la


Ver modelo. La fuente de enlace también se denomina a veces contexto de enlace.
(Xamarin.Forms usa este nombre) o contexto de datos (si ya ha realizado WPF,
reconoce esto).

3.4.2 Modo de enlace

Hay cuatro modos posibles para el enlace:


▪ Una vez: el enlace ocurre una vez cuando la vista está enlazada. El valor en el
la vista se establece desde la propiedad en el modelo de vista una vez, y todos los cambios son
ignorado Esto es útil para texto estático o imágenes que no pueden cambiar.
▪ Una forma: el enlace va de origen a destino solamente. Cada vez que la vista
cambios de modelo, la vista se actualiza. Esto tiene sentido para controles estáticos como
etiquetas donde el valor en la vista nunca puede ser actualizado por el usuario, pero la vista
el modelo puede actualizarse debido a cambios en la capa del modelo (como obtener un nuevo
valor de un servicio web).
▪ Una forma de fuente: el enlace va de destino a fuente solamente. Cada vez que el
el valor de la vista cambia, el modelo de vista se actualiza. Esto no se usa muy a menudo.
▪ Dos vías: el enlace va de origen a destino y de destino a origen. Cada
cada vez que cambia la propiedad en el modelo de vista, se actualiza el valor en la vista,
y cada vez que cambia el valor en la vista, la propiedad en el modelo de vista es
actualizado. Para controles como cuadros de texto, casillas de verificación o botones de opción, esto suele ser
El modo de enlace predeterminado.

3.4.3 El enlace no es multiplataforma


El enlace es específico de la plataforma, y siempre se establece en la capa de vista. Tiene que ser, ya que
necesita comprender los widgets de la interfaz de usuario para poder configurar los datos en ellos y escuchar
actualizaciones
En nuestra calculadora de raíz cuadrada, necesitamos vincular el cuadro de texto que el usuario usa para
ingrese el número a la propiedad Número en el modelo de vista, enlace el botón a
SqrtCommand , y luego vincule la etiqueta del resultado a la propiedad Result .
El enlace debe ser específico de la plataforma para comprender los widgets de la interfaz de usuario lo suficientemente bien
para monitorear los cambios de valor de la capa de vista. En la figura 3.14, el enlace necesita saber cómo
para detectar cambios en el texto en el cuadro de texto (por ejemplo, manejando un texto modificado
evento) y cómo detectar un toque en el botón (manejando un evento de clic). En la vista
lado del modelo, el enlace escuchará las notificaciones de propiedades modificadas de
Interfaz INotifyPropertyChanged para saber cuándo se ha actualizado el modelo de vista.
Una vez que recibe esta notificación, necesita saber cómo indicarle a la IU que actualice, como
como saber decirle a la etiqueta que muestre el resultado.

Page 101
Unión 71

La propiedad Text del TextBox está vinculada a una propiedad llamada "Número" en el modelo de vista.
El enlace encuentra Número y establece la propiedad Texto para que sea ese valor.

El enlace conoce los cuadros de texto, por lo que escucha el evento TextChanged. Cuando esto se plantea,
leerá el valor en Texto y establecerá la propiedad Número en el modelo de vista a ese valor.

El enlace escucha el evento PropertyChanged en el modelo de vista. Cuando esto se plantea


para la propiedad Number, lee el valor y lo establece en la propiedad Text del cuadro de texto.

Caja de texto

texto de cadena pública {get; set;}


evento público EventHandler TextChanged {get;}

https://translate.googleusercontent.com/translate_f 64/131
23/2/2020 Jim Bennett

Sqrt

400
Ver modelo

Etiqueta
√ Unión
Número de cadena pública {get; set;}

20 cadena pública Resultado {get;}


texto de cadena pública {get; set;}
public ICommand SqrtCommand {get;}
Raíz cuadrada

Botón

evento público EventHandler Haga clic en {get;}


public bool Enabled {get; set;}

La propiedad Text de la etiqueta está vinculada El evento Click del botón está vinculado a una propiedad llamada
a una propiedad llamada "Resultado" en el "SqrtCommand" en el modelo de vista. El enlace encuentra
Ver modelo. El enlace encuentra Resultado y SqrtCommand. Establece la propiedad Enabled en el botón
establece la propiedad Text en ese valor. al resultado de llamar a CanExecute en el comando.

El enlace escucha a PropertyChanged El enlace conoce los botones, por lo que escucha el clic
evento en el modelo de vista. Cuando esto es evento. Cuando esto se genera, ejecuta el SqrtCommand.
generado para la propiedad Resultado, lee el
valor y lo establece en la propiedad Text de El enlace escucha el evento CanExecuteChanged en el
la etiqueta. mando. Cuando esto se plantea, vuelve a evaluar CanExecute
y establece la propiedad Enabled en el botón en consecuencia.

Figura 3.14 La vinculación conecta la vista y el modelo de vista de una manera poco acoplada, pero debe ser
específico de la plataforma para saber qué propiedades y eventos en la capa de vista usar.

VINCULANTE utiliza la reflexión, así que asegúrese SUS PROPIEDADES son visibles Binding
necesita poder encontrar las propiedades en el origen y el destino (ver modelo
y widget). Cuán bueno es el marco vinculante para encontrarlos depende de
el marco, pero es una buena práctica general hacer públicas sus propiedades
y para verificar cómo funciona el marco.

102
72 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

3.4.4 Convertidores de valor


Vincular su modelo de vista multiplataforma a su código específico de plataforma es genial, pero
¿Qué pasa con los tiempos en que los tipos e incluso los valores son diferentes entre plataformas? por
ejemplo, con cuadros de texto en iOS y Android, puede vincular el texto a una cadena
propiedad en su modelo de vista, esto funciona en ambas plataformas. El problema viene si
desea mostrar u ocultar el cuadro de texto. En Android, la visibilidad está controlada por una enumeración
llamado ViewStates ; en iOS es un booleano llamado Hidden . Normalmente en su modelo de vista,
desea una propiedad legible como ShowLabel que devuelva verdadero para el widget
siendo visible y falso por estar oculto. Esto no se asigna a la enumeración de Android o
la propiedad iOS Hidden (es lo contrario, porque en iOS true significa que el widget es
oculto , por lo que no es visible).
La forma de evitar esto es a través de convertidores de valor. Como recordarán, la vista
El modelo es una capa de conversión de valor (así como una capa lógica de interfaz de usuario) para que pueda hacer algunas cosas,
pero debido a que es multiplataforma, no puede convertir valores a valores específicos de la plataforma. Esta
significa que debemos tener una pequeña parte de nuestra conversión de valor en código específico de la plataforma,
utilizando convertidores de valor . Estas son clases con el propósito singular de convertir de
ver tipos de modelos para ver tipos y volver a convertir de tipos de vista a ver modelos
tipos. Aunque queremos mantener tanta lógica de interfaz de usuario en el código multiplataforma como podamos,
los convertidores de valor específicos de la plataforma a veces son necesarios, ya que tienen que saber
sobre las implementaciones específicas de la plataforma, y pueden encapsularse de una manera
eso los hace comprobables por unidad.
Al vincular, puede indicarle al marco de vinculación que use un valor de configuración particular
verter Cuando se actualiza una propiedad en el modelo de vista, se lee el marco de enlace
el nuevo valor del modelo de vista, convierte el valor utilizando el convertidor de valor y
establece el valor convertido en la vista. Por el contrario, cuando la vista se actualiza, el enlace
framework leerá el valor de la vista, lo convertirá de nuevo usando el convertidor de valor,
y establezca el valor en el modelo de vista. Esto se muestra en la figura 3.15.
A diferencia de las notificaciones de propiedades modificadas, no hay una interfaz estándar para
convertidores de valor disponibles en todas partes. Microsoft definió uno llamado IValueConverter
para usar en aplicaciones WPF, pero esto no está disponible en las bibliotecas .NET Standard, iOS o
Aplicaciones de Android En cambio, una serie de marcos MVVM proporcionan sus propias versiones,
que son idénticos
En MvvmCross hay IMvxValueConverter . Esta interfaz es idéntica a IValue-
Convertidor y tiene dos métodos: convertir para ir de origen a destino (convertir
el valor del modelo de vista a uno que el widget espera), y ConvertBack para pasar de tar-
llegar al origen (convirtiendo del valor del widget a uno que el modelo de vista está esperando).
Esta interfaz se muestra en la siguiente lista. Para crear un convertidor de valor, puede
implemente esta interfaz en su clase y pase su clase a la capa de enlace.

https://translate.googleusercontent.com/translate_f 65/131
23/2/2020 Jim Bennett

Page 103
Unión 73

BoolToHiddenValueConverter convierte un booleano


representando el espectáculo del modelo de vista a uno
representando hide invirtiendo el valor.
Ver
BoolToViewStatesValueConverter convierte un Ver

Espectáculo booleano representativo del modelo de vista


Jim
a un valor de enumeración de ViewStates mediante la conversión deJim
verdadero a
ViewStates.Visible y false to ViewStates.Gone.

Vista de iOS Ver modelo Vista de Android

UILabel Vista de texto


bool público
público bool oculto ViewStates públicos
ShowName {get; set;}
{get; set;} Visibilidad {get; set;}

La propiedad oculta de La propiedad de visibilidad


el UILabel está obligado a del TextView está vinculado
una propiedad llamada BoolToHiddenValueConverter a una propiedad llamada
"ShowName" en el BoolToViewStatesValueConverter
"ShowName" en el
Ver modelo. Ver modelo.
El enlace busca la propiedad "ShowName"
en el modelo de vista y lo encuentra.

El enlace escucha las actualizaciones de ShowName.


Cuando la propiedad cambia, pasa el
valor a través del convertidor de valor.

Oculto se actualiza usando La visibilidad se actualiza usando


el valor que sale el valor que sale
del convertidor de valor. del convertidor de valor.

Figura 3.15 Los convertidores de valor le permiten convertir un valor del modelo de vista a un tipo que
La vista está esperando.

Listado 3.11 La interfaz IMvxValueConverter

interfaz pública IMvxValueConverter Convierte cambios de


{ valor fuente (ver modelo)
conversión de objeto (valor de objeto, tipo targetType, al valor objetivo (ver)
parámetro de objeto, cultura CultureInfo);

object ConvertBack (valor del objeto, Tipo targetType,


parámetro de objeto, cultura CultureInfo);
}
Convierte cambios desde el objetivo (ver)
valor al valor de origen (ver modelo)

Página 104
74 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

El primer parámetro en estos dos métodos ( valor ) es el valor que desea convertir.
Estos métodos luego devuelven el valor convertido. El parámetro targetType te dice
a qué tipo debe convertir el método, aunque esto normalmente se ignora como valor
Los vértices suelen ser bastante específicos.
El parámetro parámetro puede ser útil si desea tener el convertidor de valor
admite algunas conversiones diferentes y modifica el comportamiento cuando se llama. Para examen-
Por ejemplo, podría tener un convertidor de valor que convierta números que representan cantidades
de dinero a cadenas en monedas particulares, y use parámetros para especificar qué monedas
Rency a utilizar (como £ o $). El parámetro de cultura es útil si estás apoyando
múltiples idiomas, porque le permite cambiar su salida en función de la actual
configuración de localización. Por ejemplo, si está convirtiendo un número en una cadena, puede
cambiar el símbolo decimal a un punto o una coma según el país del usuario
pasando la información cultural al método ToString en el número.
Al igual que con los comandos, no se proporcionan convertidores de valores listos para usar con .NET
Framework, pero la mayoría de las bibliotecas MVVM proporcionan algunas estándar, como la conversión
Booleanos a banderas de visibilidad. Por ejemplo, MvvmCross proporciona MvxVisibilityValueC-
inversor para asignar valores verdaderos a valores visibles y falsos a invisibles, y MvxInvert-

https://translate.googleusercontent.com/translate_f 66/131
23/2/2020 Jim Bennett
edVisibilityValueConverter para hacer lo contrario.

3.5 La capa de aplicación


La mayor parte de la capa de aplicación es proporcionada por el código específico de la plataforma que es
integrado en los SDK de Xamarin iOS y Android. Cuando crea sus proyectos de aplicaciones, un
algunos archivos se generarán automáticamente para usted, que contienen alguna configuración de la aplicación.
Cualquier modificación a esto generalmente será cambios específicos de la plataforma, como el manejo
notificaciones en iOS o cableado de servicios en segundo plano en Android.
Hay algunas cosas pequeñas que se pueden configurar en código multiplataforma, pero
Esto depende mucho de su marco MVVM. Lo principal que puedes controlar
Aquí está el proceso de inicio.
Normalmente, la actividad principal de Android o el controlador de vista de iOS que se carga en la aplicación
El inicio del catión se define a nivel de aplicación, pero un buen marco MVVM
le permite definir esto en código multiplataforma. Esto generalmente se hace especificando el
primer modelo de vista a utilizar. Esto le permite poner lógica en la capa de aplicación que puede ser
compartido en ambas plataformas y ser probado en la unidad.
Un buen ejemplo de una situación en la que podría hacer esto es una aplicación que requiere un
inicio de sesión de usuario. Cuando la aplicación se carga por primera vez, el código de su aplicación compartida puede ver si
Ya existe una cuenta de usuario válida de algún código compartido de administración de usuarios. Sí hay
es una cuenta válida, puede cargar la pantalla principal de su aplicación desde su modelo de vista, y si
no, puede cargar el modelo de vista de pantalla de inicio de sesión. Si esta lógica está en código multiplataforma,
solo tendrá que escribir esto una vez, no una vez por plataforma.
Además, la capa de aplicación puede definir cómo las diferentes clases en su aplicación
estan conectados. Por ejemplo, puede garantizar que SquareRootViewModel sea compatible
construido automáticamente utilizando una implementación de SquareRootCalculator como
Parámetro del constructor ISquareRootCalculator .

Page 105
Navegación 75

3.6 Navegación
La capa de modelo de vista proporciona tanta lógica de IU como sea posible, y parte de esta lógica de IU es
relacionado con la navegación: el acto de moverse de una pantalla a otra en la aplicación.
Imagine una aplicación de directorio de empresas que tiene dos pantallas: una con una lista de
ees, y uno que muestra los detalles sobre un empleado. La aplicación proporciona navegación.
de la lista a un solo empleado, cuando toca el nombre de una persona en la lista
primera pantalla, una nueva pantalla muestra los detalles sobre esa persona, como se muestra en la figura 3.16.

Mi directorio de empresas

1. Toque un nombre en Lauren Ipsum Lauren Ipsum

La pantalla de personas.
Aarti Effern

Figura 3.16 Navegando desde


2. La pantalla de persona
una pantalla a otra por
aparece, reemplazando Desarrollador móvil
tocando un nombre en las personas
La pantalla de personas.
lista

Este tipo de navegación es multiplataforma, independientemente de cómo se actualice la interfaz de usuario,


queremos proporcionar esta navegación en ambas plataformas. Ambas plataformas mostrarán el
nueva pantalla y pasarle datos sobre qué persona fue seleccionada. La implementación en
Cada plataforma es muy diferente.
▪ Android conceptualiza cada pantalla como una actividad separada bajo la cual el usuario está
tomar, y el usuario tiene que expresar una intención de cambiar su actividad.
▪ iOS piensa en cada pantalla como una vista de una parte de la aplicación, y el usuario sigue
de una vista a otra

Ambas implementaciones significan lo mismo desde la perspectiva del usuario: ve un


pantalla diferente, pero los términos utilizados y las clases subyacentes y las llamadas a métodos son
muy diferente.

¿Qué es una "pantalla"?


Se utilizan muchos términos diferentes para definir lo que vemos en una aplicación. En cualquier momento, tu
la aplicación llenará la pantalla del dispositivo y mostrará algunos widgets de IU que muestran el estado o
proporcionando comportamiento. En varios momentos en su aplicación, generalmente cuando toca algo, el
toda la pantalla se reemplaza con otra pantalla completa de widgets.

En este libro usaré el término pantalla para referirme a cada interfaz de usuario de pantalla completa, así que en nuestro
aplicación de calculadora solo hay una pantalla que muestra la calculadora de raíz cuadrada. En el com
aplicación de directorio de pany, habría dos pantallas, la primera que muestra la lista de personas
ple, y el segundo que muestra los detalles de una persona específica.

https://translate.googleusercontent.com/translate_f 67/131
23/2/2020 Jim Bennett

Page 106
76 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

Para ver cómo podemos resolver este problema de una manera multiplataforma usando MVVM, primero
debemos considerar lo que realmente queremos decir cuando pensamos en las pantallas de una aplicación desde un
Perspectiva MVVM. Cuando vemos una pantalla en nuestra aplicación, lo que realmente estamos viendo es una vista
y un modelo de vista: la vista proporciona los widgets de IU y el modelo de vista proporciona
estado y comportamiento. Cuando cambiamos las pantallas, estamos cambiando tanto la vista como la vista
modelo que se muestran. Entonces, ¿qué controla este cambio de pantallas? Qué capa maneja
la navegación?

Puede tener múltiples vistas y ver modelos en una pantalla


En nuestros ejemplos simples, hay una vista y un modelo de vista por pantalla, pero nada
te impide tener más. Podría tener una pantalla compuesta de varias partes, y
cada parte sería su propia vista y modelo de vista.

Por ejemplo, con la aplicación de directorio de la empresa en una tableta en orientación horizontal,
habría suficiente espacio para tener la lista de personas en el lado izquierdo y los detalles
sobre la persona de la derecha. Esa es una vista principal que muestra dos vistas y vistas
modelos. En orientación vertical, la aplicación mostraría una vista y un modelo de vista para
lista y tocar una persona reemplazaría esa vista con la vista y vista de persona
modelo.

Algo tiene que garantizar que el modelo de vista correcto esté vinculado a la vista correcta, por lo que
debe ser un enlace entre la vista y el modelo de vista. Hay dos formas de hacer
esto: ver primero y ver modelo primero. Ambos enfoques dependen de que exista
algo, generalmente en la capa de la aplicación, que define estos enlaces.

3.6.1 Ver primero


Ver primero significa que la vista es el conductor detrás de la navegación (figura 3.17). En la aplicación
inicio, la capa de la aplicación cargará una vista, y cuando se carga la vista, algo (tal vez
algún código en la capa de la aplicación, o incluso en la vista en sí) creará el correspondiente
ver modelo y atarlo. Cuando navega a otra pantalla, la vista es responsable
ble por esto. Sabrá a qué vista necesita navegar y mostrará esa vista,
que a su vez hace que su modelo de vista sea creado y vinculado.

3.6.2 Ver modelo: primero


Ver modelo: primero significa que el modelo de vista es el conductor detrás de la navegación (figura
3.18). La capa de aplicación cargará un modelo de vista al inicio de la aplicación, y esta carga del
ver modelo hará que la vista se cree, se vincule al modelo de vista y se muestre.
Cuando navega a otra pantalla, el modelo de vista es responsable de esto. Va a
saber a qué modelo de vista navegar e interactuar con algo (generalmente pro
asistido por el marco MVVM que está usando) para crear el nuevo modelo de vista y su
vista asociada

Page 107
Navegación 77

1. La aplicación crea 3. Tocando un nombre


PeopleView PersonView
PeopleView. crea un PersonView
Mi directorio de empresas Lauren Ipsum y muestra la pantalla.

Lauren Ipsum

Aarti Effern

Desarrollador móvil

2. PeopleView crea 4. PersonView crea


PeopleViewModel PersonViewModel y
y se une a eso. se une a eso.
PeopleViewModel PersonViewModel

Figura 3.17 Navegación de primera vista: la vista impulsa la creación de modelos de vista y navega a
otras vistas.

PeopleView PersonView

Mi directorio de empresas Lauren Ipsum

Lauren Ipsum

Aarti Effern

https://translate.googleusercontent.com/translate_f 68/131
23/2/2020 Jim Bennett

Desarrollador móvil

2. El marco 4. El marco crea


crea PeopleView PersonView y enlaces
y une la vista el modelo de vista para ello.
modelarlo.
PeopleViewModel PersonViewModel

1. La aplicación crea 3. Al tocar un nombre se ejecuta un


PeopleViewModel. comando en PeopleViewModel
que crea un PersonViewModel
y lo muestra

Figura 3.18 Modelo de vista: primera navegación: el modelo de vista impulsa la creación de vistas utilizando
MVVM framework y navega a otros modelos de vista.

108
78 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

3.6.3 ¿Cuál usar?


El enfoque más popular con diferencia es el modelo de vista: primero. Si tienes la lógica para cargar
vistas en la capa de vista, tiene más código específico de plataforma, y esta plataforma-
El código específico es difícil de probar, excepto manualmente. Escribir pruebas unitarias contra código UI es
más difícil que escribirlos contra un código que no sea UI. Si la lógica está en el modelo de vista, usted
tiene más lógica en su capa multiplataforma, por lo que hay menos código para escribir y más
código que puede probar por unidad.
La mayoría de los marcos MVVM proporcionan un servicio de navegación de alguna descripción, un servicio
vicio que le permite navegar a diferentes vistas o ver modelos. Este servicio es siempre
expuesto a través de una interfaz que puede usar desde sus modelos de vista (y simulacro para
prueba) y le permite navegar de una manera que no está estrechamente acoplada a una clase de vista.
En algunos marcos, esto se hace navegando a un modelo de vista, y en otros es por
navegar utilizando una clave (como un valor de cadena único) que se ha vinculado a una vista
y ver modelo. MvvmCross navega a través del modelo de vista, y es esta navegación que estaremos
utilizando en este libro.

3.7 Revisando la aplicación de calculadora de raíz cuadrada


Has visto la aplicación de calculadora de raíz cuadrada desglosada capa por capa, así que tomemos un
momento de dar un paso atrás y ver la imagen más grande, usando una imagen más grande. Al principio
del capítulo presenté una figura que mostraba las interacciones del usuario con la aplicación. Fueron
ahora en una posición para expandir esta figura, completando todas las diferentes interacciones
entre las diferentes capas. Esto se muestra en la figura 3.19.
Tómese un momento para estudiar este diagrama y siga el flujo a través de la aplicación. Muestra
mucho de lo que ya hemos hablado.
La aplicación se inicia y lanza una vista y un modelo de vista, idealmente usando view-model–
primera navegación A medida que se crean, el enlace conecta el estado y el comportamiento en
el modelo de vista a la interfaz de usuario: las propiedades están vinculadas a un cuadro de texto y una etiqueta, y el
El comando está vinculado a un botón. A medida que el usuario ingresa texto, el modelo de vista se actualiza a través de
el enlace, que a su vez empuja el valor al modelo. Al hacer clic en el botón exe-
corta un comando que calcula la raíz cuadrada y genera una notificación de cambio de propiedad
catión. El enlace detecta este cambio de propiedad, que actualiza la interfaz de usuario.
Este flujo parece simple, pero abarca la mayor parte de MVVM:
▪ El modelo es una capa separada que tiene lógica empresarial y utiliza propiedades de
tipos que tienen sentido en el dominio empresarial.
▪ El modelo de vista envuelve la capa del modelo y expone el estado y el comportamiento al
capas anteriores, convirtiendo el estado de tipos de negocio a tipos de IU.
▪ El enlace se ubica sobre el modelo de vista y lo "pega" a la vista.
▪ La vista expone el estado y el comportamiento a través de widgets en la pantalla que el usuario
puede entender e interactuar con

Tenemos una capa de modelo que es distinta, multiplataforma, comprobable por unidades, más fácil de mantener,
y más fácil de evolucionar. También tenemos una capa de modelo de vista que es distinta, multiplataforma,

Page 109
Revisando la aplicación de calculadora de raíz cuadrada 79

La aplicación comienza El usuario escribe "400" El usuario toca El modelo de vista plantea un
y la vista en el cuadro de texto. la plaza evento cambiado de propiedad
y ver modelo Botón de raíz con el nombre de la propiedad

https://translate.googleusercontent.com/translate_f 69/131
23/2/2020 Jim Bennett
son creados. El enlace detecta Resultado. La Unión
el texto del cuadro de texto La Unión detecta el evento
La Unión evento cambiado, lee detecta el y lee la propiedad.
la capa mira hacia arribael valor dentro de evento de toque de botón
las propiedades en cuadro de texto y pasa y ejecuta el El enlace lee el
la vista y la vista a la propiedad SqrtCommand on valor de Resultado y conjuntos
modelo. Agrega en el modelo de vista. El modelo de vista. en el cuadro de texto de resultados.
controladores de eventos
para el texto Sqrt Sqrt Sqrt

cambiando en el √
Raíz cuadrada
400 400 400

texto de número
cuadro y el clic √ √ √
del botón Agregar. 20

También agrega un
controlador de eventos Raíz cuadrada Raíz cuadrada Raíz cuadrada

para la propiedad
evento cambiado en
El modelo de vista.
Finalmente, establece el
Ver
valores en la vista
basado en el
valores en el
Ver modelo. Unión

Número obtiene / establece


Número en el
modelo, convirtiendo Ver modelo
de un doble en
Número "400" "400" "400" "400" "400"
el modelo a un
cadena en la vista Resultado "20" "20" "20"
modelo. Resultado obtiene
SqrtCommand Ejecutar
Resultado de la
modelo, convirtiendo
a una cuerda.
El comando Sqrt
Modelo
envuelve una llamada a Sqrt
en el modelo Número 400 400 400 400 400

Resultado 20 20 20 20

Sqrt Sqrt ()

El modelo de vista El SqrtCommand en El modelo de vista lee


convierte la cadena el modelo de vista se ajusta el doble valor de
valor de "400" a un el método Sqrt en Resultado y conversiones
doble valor de 400 el modelo. Cuando el a una cuerda.
y lo pasa por el comando se ejecuta
a la propiedad Number el método Sqrt es
en el modelo llamado y el resultado
se establece en 20.

Figura 3.19 La calculadora completa de raíz cuadrada, que muestra las interacciones entre todas las capas
de MVVM

Page 110
80 C APÍTULO 3 MVVM: el patrón de diseño del modelo vista-vista-modelo

comprobable por unidad, más fácil de mantener y más fácil de evolucionar. Tenemos una capa de enlace y un
delgada capa de interfaz de usuario que es específica de la plataforma.
Ahora está armado con más conocimiento sobre MVVM. En el próximo capítulo vamos a
eche un vistazo al ejemplo de Hello World del capítulo 2 y vea lo que está sucediendo
en el código También ampliaremos la aplicación utilizando un complemento Xamarin multiplataforma para hacer
te dice "hola".

Resumen
En este capítulo aprendiste que
▪ Los modelos son multiplataforma y de prueba unitaria, y representan datos en el negocio.
nivel lógico o de dominio, no en el nivel de la interfaz de usuario.
▪ Los modelos de vista son multiplataforma y de prueba unitaria, y representan estados y
comportamiento a través de propiedades y comandos. Ver modelos actúan como una conversión
capa entre datos o acciones en el nivel de IU y datos o métodos en el modelo.
▪ La capa de vista específica de la plataforma y el modelo de vista multiplataforma comuni-
catear a través de un aglutinante, una capa flojamente acoplada que generalmente es proporcionada por un marco
trabajo que mantiene la vista (destino de enlace) y el modelo de vista (origen de enlace) en
sincronizar
▪ Para navegar entre diferentes pantallas en su aplicación, puede usar view-first naviga-
para que la vista administre la navegación, o ver modelo-primera navegación a
haga que el modelo de vista lo gestione. Ver modelo: primero es preferible, ya que puede unir
prueba esta navegación.
▪ .NET Framework tiene algunas interfaces y clases que ayudan a implementar
su aplicación usando MVVM, pero para implementar completamente el patrón puede usar un tercero
marco de fiesta como MvvmCross, MVVM Light o Caliburn.Micro.

https://translate.googleusercontent.com/translate_f 70/131
23/2/2020 Jim Bennett

Página 111

44
Hola de nuevo, MVVM—
entender y mejorar
nuestra sencilla aplicación MVVM

Este capítulo cubre


▪ Unamirada detallada al código de Hello Cross-Platform
Aplicación mundial del capítulo 2
▪ ClasesMvvmCross que proporcionan una implementación base de un
ver modelo, un comando y alguna lógica de aplicación multiplataforma
▪ Cómo usar MvvmCross para vincular vistas de iOS y Android a
ver modelo
▪ Usode complementos de Xamarin para agregar envolturas multiplataforma
funcionalidad específica de la plataforma
▪ Usode la inversión de control para acoplar libremente su código para la unidad
pruebas
▪ Crear y vincular un comando
▪ Agregar código al modelo de vista para que su aplicación le hable

81

112
82 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

4.1 Una inmersión más profunda en nuestra aplicación Hello Cross-Platform World
Ahora que hemos cubierto MVVM en detalle, es una buena oportunidad para revisar Hello
La aplicación Cross-Platform World que creó en el capítulo 2 para ver qué hace el código y cómo funciona
cabe en las capas para una aplicación Xamarin. Construiste la aplicación usando la extensión MvvmCross
sion, que creó una sencilla aplicación Hello World en la que se edita el valor en un cuadro de texto
actualizado una etiqueta para que coincida. Era una aplicación multiplataforma, y lo probamos cambiando
una cadena en el proyecto principal y ver que ambas aplicaciones se actualizaron.
Comencemos a trabajar a través de las capas del modelo de abajo hacia arriba.

https://translate.googleusercontent.com/translate_f 71/131
23/2/2020 Jim Bennett
4.1.1 El modelo
Comenzando de abajo hacia arriba, pensemos en el modelo. Esta es una aplicación simple con un
valor de cadena única, por lo que realmente no hay una capa de modelo como tal. Puedes pensar en el
hola campo de cadena como modelo.
No hay mucho más que ver aquí, así que pasemos a la vista más importante:
capa modelo

4.1.2 El modelo de vista


En el proyecto HelloCrossPlatformWorld.Core, tiene un modelo de vista llamado First-
ViewModel (figura 4.1). Este modelo de vista "envuelve" el modelo (la cadena de saludo ) y
expone su valor a través de su estado, exponiendo una propiedad llamada Hello .
Lo primero que puede notar sobre este modelo de vista es que tiene una clase base: Mvx-
ViewModel . Esta clase es proporcionada por MvvmCross (todas las clases de MvvmCross comienzan con Mvx
e interfaces comienzan con IMvx ), y le brinda una implementación básica de un modelo de vista.
Lo principal que proporciona son las notificaciones de cambio de propiedad: implementa
INotifyPropertyChanged y tiene algunos métodos para generar el evento PropertyChanged .

FirstViewModel vive en los ViewModels FirstViewModel deriva de


carpeta de HelloCrossPlatformWorld. MvxViewModel, una vista base
Proyecto central. clase de modelo de MvvmCross.

La cadena hola actúa como modelo


capa para este ejemplo trivial.

Figura 4.1 La estructura del proyecto principal que muestra la ubicación de la clase FirstViewModel

113
Una inmersión más profunda en nuestra aplicación Hello Cross-Platform World 83

Si observa la propiedad Hello , también puede notar algo interesante en el conjunto


método.

Listado 4.1 Establecer un valor y generar un evento cambiado de propiedad

cadena pública Hola


{
get {return hola; }
set {SetProperty (ref hola, valor); }
}

Normalmente en un modelo de vista, verificaría si el campo era diferente del valor,


y si es así, establecería el campo y generaría el evento PropertyChanged . Aquí, sin embargo, estamos
llamando a un método, SetProperty . Esto viene como parte de MvxViewModel y envuelve el
lógica de configuración habitual: verificará el valor y solo actualizará la propiedad y elevará
evento cambiado de propiedad si es diferente. También puede notar que la cadena es pasada por
ref . Esto significa que se pasa una referencia al campo de cadena real en lugar de una copia,
para que dentro del método SetProperty pueda actualizar el valor del campo. Eso
no proporciona ninguna magia adicional, solo está ahí para ahorrar en escribir: tres líneas de código
Convertirse en uno.
Este método también devolverá un valor booleano: verdadero significa que el valor cambió y
fue actualizado; falso significa que no se actualizó. Esto es útil si necesita realizar
otras acciones si el valor cambió, como generar notificaciones de cambio de propiedad para
otras propiedades que usan este valor.

4.1.3 La capa de aplicación


Antes de mirar la vista, vale la pena hacer un breve recorrido por la capa de aplicación. Mvvm-
Cross proporciona algo de código en la capa de aplicación: algunos son específicos de la plataforma en los dos
proyectos de aplicaciones, y algunos son multiplataforma en el proyecto principal. Por el momento, todos nosotros
realmente me importa es la parte multiplataforma. Esto está en una clase llamada Aplicación dentro de App.cs,
como se muestra en la figura 4.2.

App.cs contiene multiplataforma


código de capa de aplicación.

https://translate.googleusercontent.com/translate_f 72/131
23/2/2020 Jim Bennett

Figura 4.2 El código de la capa de aplicación multiplataforma se encuentra en App.cs en el proyecto principal.

114
84 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

La clase de aplicación se deriva de MvxApplication , una clase de aplicación base de MvvmCross.


Esto implementa solo un método: Inicializar . La línea aquí que es de interés para
nosotros es el siguiente.

Listado 4.2 Registro del modelo de vista que se muestra al inicio de la aplicación

RegisterNavigationServiceAppStart <ViewModels.FirstViewModel> ();

Esta llamada RegisterNavigationServiceAppStart le dice al código de la aplicación MvvmCross


que cuando se inicia la aplicación, lo primero que se debe mostrar es FirstViewModel . Si tu
recuerde volver a la navegación MVVM en el último capítulo, verá que esto es view-
modelo: primera navegación: el modelo de vista se registra cuando se inicia la aplicación, por lo que es el primer
Lo que se muestra en el lanzamiento. Para mostrar este modelo de vista, MvvmCross buscará el corre-
ver y mostrar eso.
Debe decirle a MvvmCross qué vista es la vista correcta para cada modelo de vista. Suerte-
Sin embargo, no es necesario que lo diga explícitamente; puedes hacerlo por el nombre. Por convenio
Además, la vista y el modelo de vista tienen los mismos nombres, excepto el sufijo, y
MvvmCross usa esto para determinar qué vista mostrar para cada modelo de vista. Existen
otras formas de decirlo si no quieres seguir esta convención, pero por ahora nos quedaremos
a la convención de nomenclatura. El modelo de vista aquí se llama FirstViewModel , para mostrar
MvvmCross buscará una vista llamada FirstView .
Una vez que se carga la vista, se crea una nueva instancia de la clase de modelo de vista, y esto
se establece como la fuente de enlace de la vista.

4.1.4 La vista
Nuestra capa de vista se divide en los dos proyectos de aplicación, así que veámoslos uno por uno,
comenzando con Android.

T HE A VISTA ndroid
En el proyecto de Android, la vista de Android se define como una Actividad , que utiliza un lay-
fuera del archivo para definir la interfaz de usuario. ( Activity es la clase de código subyacente de Android para una pantalla completa
ventana; los veremos con más detalle en el capítulo 9.)
La actividad de vista se encuentra dentro de una carpeta llamada Vistas, y se llama FirstView (figura
4.3) Cada actividad puede construir su UI en código, pero normalmente carga la UI desde un
recurso de diseño: un archivo XML que define los widgets y los contenedores de diseño (especial
widgets que no tienen componentes visibles pero que se utilizan para diseñar otros widgets,
como organizar uno debajo de otro en una pila vertical). La actividad de FirstView con-
No tiene nada de interés para nosotros aquí. Lo interesante está dentro de FirstView.axml: el
recurso de diseño que carga.

115 de 1189.
Una inmersión más profunda en nuestra aplicación Hello Cross-Platform World 85

El proyecto de la aplicación de Android

Recursos del proyecto como imágenes


o diseños en vivo aquí.

https://translate.googleusercontent.com/translate_f 73/131
23/2/2020 Jim Bennett

Los diseños que definen la interfaz de usuario viven aquí.

FirstView.axml es el que queremos editar.

Android usa clases derivadas de Activity


para código subyacente para la interfaz de usuario. Estos viven aquí.

Figura 4.3 La estructura del proyecto de la aplicación de Android que muestra la ubicación de FirstView.axml
archivo de diseño

116
86 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

Figura 4.4 FirstView.axml en la vista del diseñador

En el proyecto de Android hay una carpeta llamada Recursos que contiene cualquier archivo de recursos que
necesidades de la aplicación, como imágenes, cadenas y archivos de diseño. Puede encontrar los diseños en la página
fuera de la carpeta. Si observa allí, verá el diseño de nuestra primera vista: FirstView.axml.
Si abre este recurso de diseño, obtendrá una vista con pestañas con una pestaña para un diseñador
(figura 4.4) y uno para la fuente sin procesar (figura 4.5). Es la vista de la fuente que estamos inter-
probado en.
En esta pestaña Fuente, verá una serie de nodos en el XML que representan cada uno
elemento visual Algunos son diseños, que son elementos que contienen otros elementos y ponen
ellos de cierta manera, y algunos son widgets. Entraremos en esto con más detalle en
capítulo 9. Por ahora, estos son los conceptos básicos de los elementos en este diseño:
▪ RelativeLayout: un elemento de diseño que le permite posicionar sus elementos secundarios.
Tive al contenedor o el uno al otro. Por ejemplo, podrías poner algo en
la parte superior del contenedor, o coloque algo debajo de un elemento en particular.
▪ FrameLayout: un diseño que contiene un solo elemento o elementos que se colocan
uno encima del otro (en el eje Z, por lo que sale de la pantalla).
▪ LinearLayout: un diseño que apila elementos de forma horizontal o vertical.

https://translate.googleusercontent.com/translate_f 74/131
23/2/2020 Jim Bennett

Página 117
Una inmersión más profunda en nuestra aplicación Hello Cross-Platform World 87

Figura 4.5 FirstView.axml en la vista de origen

▪ EditText : un control de entrada de texto.


▪ TextView : un control de texto estático.

Los dos nodos que nos interesan, EditText y TextView , se muestran a continuación:
listado de ing.

Listado 4.3 Widgets de enlace en el recurso de diseño para el modelo de vista

<Editar texto
android: layout_width = "match_parent"
android: layout_height = "wrap_content"
android: textSize = "40dp"
local: MvxBind = "Texto Hola" />
<TextView
android: layout_width = "match_parent" Ambos widgets tienen un
android: layout_height = "wrap_content" Conjunto de atributos MvxBind.
android: textSize = "40dp"
local: MvxBind = "Texto Hola" />

118
88 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

El EditarTexto es un-una caja de control de entrada de texto en texto editable. TextView es texto estático: un
etiqueta. En el XML de estos controles, verá una serie de atributos establecidos en
El espacio de nombres de Android . Estas son propiedades de control estándar, como su tamaño. En
Además, ambos controles tienen un atributo interesante en el espacio de nombres local .

Listado 4.4 MvvmCross usa un atributo para especificar el enlace en los archivos de diseño de Android

local: MvxBind = "Texto Hola"

Como es de esperar del nombre del atributo, MvxBind es un atributo de Mvvm-


Cruz que hace vinculante. Proviene del espacio de nombres XML local (definido como
xmlns: local = "http://schemas.android.com/apk/res-auto" ), que es un especial
el espacio de nombres solía referirse a todos los recursos que provienen de su aplicación, ya sea
código que ha escrito o código de bibliotecas externas, como el Android MvvmCross
Paquetes NuGet. Al establecer estos atributos MvxBind , le está diciendo a MvvmCross que se enlace
la propiedad Text en ambos controles a una propiedad llamada Hello en el enlace
fuente: una instancia de FirstViewModel . La figura 4.6 muestra esta unión.

1. Se desencadena el evento TextChanged en EditText.


El enlace detecta esto, lee la propiedad Text y
actualiza la propiedad Hello en FirstViewModel.

FirstViewModel

Hola xamarin en acción


Unión Hola

https://translate.googleusercontent.com/translate_f 75/131
23/2/2020 Jim Bennett
Hola xamarin en acción

2. El evento PropertyChanged en FirstViewModel es


despedido. El enlace detecta esto, lee la propiedad Hello,
y actualiza la propiedad Text en TextView.

Figura 4.6 El enlace detecta el evento en la vista y actualiza la vista


modelo, y detecta eventos en el modelo de vista y actualiza la vista.

T HE I OS VISTA
Al igual que Android, iOS tiene dos archivos para una vista: un archivo de diseñador que define los widgets de la interfaz de usuario
y diseño, y un archivo de controlador de vista que proporciona el código subyacente (veremos
estos en más detalle en el capítulo 11). Estos viven en la carpeta Vistas en Hello-
Proyecto CrossPlatformWorld.iOS (figura 4.7).
A diferencia de Android, los archivos de diseño (en este caso, FirstView.storyboard) en iOS son
no es muy legible para los humanos y no está destinado a ser editado en la fuente. En cambio, tu
debería usar el diseñador para editarlos. Esto significa que no puede agregar su enlace

Page 119
Una inmersión más profunda en nuestra aplicación Hello Cross-Platform World 89

El proyecto de la aplicación iOS

Vistas (los diseños de la interfaz de usuario y el código subyacente)


vivir aquí.

Parte del código subyacente para FirstView;


Este archivo puede ser editado.

El guión gráfico para FirstView; este archivo es


editable en el diseñador visual.

Parte del código subyacente para FirstView;


Este archivo es autogenerado.

Figura 4.7 Las vistas en iOS viven en la carpeta Vistas con un controlador de vista llamado FirstView
y un guión gráfico llamado FirstView.storyboard.

usando atributos como lo hiciste en Android. En su lugar, puede agregar el enlace en el


código subyacente: en el controlador de vista FirstView , ubicado en FirstView.cs.
Veamos ahora las partes importantes de este código.

Listado 4.5 En iOS, el enlace se realiza en el controlador de vista

FirstView deriva de MvxViewController, Se llama a ViewDidLoad cuando el


una clase MvvmCross que deriva de la vista se ha cargado, así que tan pronto
UIViewController. como los widgets de IU en el
el guión gráfico se carga y el
Se muestra la vista.
clase parcial pública FirstView: MvxViewController
{
anulación pública void ViewDidLoad ()
{
base.ViewDidLoad ();

120
90 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

var set = this.CreateBindingSet <FirstView, FirstViewModel> ();


set.Bind (Label) .To (vm => vm.Hola);

https://translate.googleusercontent.com/translate_f 76/131
23/2/2020 Jim Bennett
set.Bind (TextField) .To (vm => vm.Hola); Un conjunto de enlace es un grupo
set.Apply (); de enlaces para una vista
} Una vez que el conjunto de enlace es y ver modelo.
} creado, puede ser
aplicado para establecer el TextField también está vinculado
La etiqueta está vinculada a valores iniciales y comienzo a la propiedad Hello en
la propiedad Hello en escuchando cambios. El modelo de vista.
El modelo de vista.

Este código muestra la clase FirstView derivada de MvxViewController, un MvvmCross


ver la clase de controlador que a su vez deriva de la base iOS UIViewController . Ver
los controladores son responsables del ciclo de vida de la vista, cuando se muestra, cuando se muestra
oculto, y varios estados intermedios. En este caso, nos estamos conectando cuando la vista
se carga (y se crean todos los widgets) anulando el método ViewDidLoad . Una vez
la vista se carga, el código crea un conjunto de enlaces, una colección de enlaces entre
los controles y la fuente de enlace (el modelo de vista).
Si hace doble clic para abrir FirstView.storyboard, se abrirá en un diseñador. En esto
verá una vista única con dos controles: una etiqueta y un cuadro de texto. Si hace clic en cada uno,
verá que ambos tienen nombres, como se muestra en la figura 4.8.

El UILabel tiene el nombre "Etiqueta". Esto crea


una propiedad Label en el controlador de vista.

El UITextField tiene el nombre "TextField". Esta


crea una propiedad TextField en el controlador de vista.

Figura 4.8 El storyboard de iOS tiene dos controles: uno llamado Label y otro llamado TextField .

Page 121
Una inmersión más profunda en nuestra aplicación Hello Cross-Platform World 91 91

Es posible que haya notado que, además de FirstView.cs y FirstView.storyboard, también hay
un archivo llamado FirstView.designer.cs. Esto se genera automáticamente cada vez que cambia el almacenamiento
ryboard, y contiene asignaciones de elementos en el guión gráfico a las propiedades de
Clase FirstView Si lo abre, verá las dos propiedades que se muestran a continuación
listado.

El listado 4.6 Los widgets de IU nombrados en los guiones gráficos se definen como propiedades

[Toma de corriente]
[GeneratedCode ("Diseñador de iOS", "1.0")]
UIKit.UILabel Label {get; conjunto; }

[Toma de corriente]
[GeneratedCode ("Diseñador de iOS", "1.0")]
UIKit.UITextField TextField {get; conjunto; }

Estas propiedades representan la etiqueta y el cuadro de texto en el guión gráfico. Los atributos
en ellos le dicen a las herramientas que estas propiedades se generan automáticamente desde el guión gráfico
diseñador (por lo que no tiene sentido tocar este código porque sus cambios se perderán
la próxima vez que cambie el guión gráfico) y que sea un Outlet , el término de iOS para un
propiedad que representa algo en un guión gráfico. Estas dos propiedades son de tipo
UILabel , que es la clase de iOS para una etiqueta de texto estático, y UITextField , que es el
Cuadro de entrada de texto de iOS.
FirstView.designer.cs contiene una clase llamada FirstView , al igual que FirstView.cs
archivo, pero ambas declaraciones de clase están marcadas como parciales . Si no te has encontrado con esto
antes, es una forma de decir que varios archivos tienen partes de la misma clase, y que el
el compilador debe unirlo todo en una clase cuando se compila. Es genial para el código
así: podemos escribir un archivo y tener otro que se genere automáticamente en función de una interfaz de usuario
diseñador, y ambos archivos se unen para definir la clase.
Mirando hacia atrás al código de enlace, vincularemos estas dos propiedades a propiedades en
el modelo de vista dentro de FirstView.cs, de la siguiente manera.

Listado 4.7 Vinculación de widgets de iOS al modelo de vista

https://translate.googleusercontent.com/translate_f 77/131
23/2/2020 Jim Bennett
var set = this.CreateBindingSet <FirstView, FirstViewModel> (); La Unión
set.Bind (Label) .To (vm => vm.Hola); Se crea el conjunto.
set.Bind (TextField) .To (vm => vm.Hola);
set.Apply (); La etiqueta es
El conjunto de enlace es atado a la
aplicado, configurando el El TextField es Hola propiedad
valores iniciales y atado a la
comenzando la escucha Hola propiedad
para actualizaciones

Este código comienza creando un conjunto de enlaces, de tipo MvxFluentBindingDescription-


Set: otra clase MvvmCross. Este conjunto de enlaces se escribe en función de la vista y el
ver modelo, y una vez creado, se puede usar para vincular controles a propiedades en la vista
modelo.

Page 122
92 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

Cuando se vincula a widgets de UI, generalmente solo hay una propiedad o evento que es
interesado en. Las etiquetas muestran texto estático, por lo que la mayoría de las veces solo le interesa
en la encuadernación de este texto. Lo mismo ocurre con los cuadros de texto: generalmente solo le interesa
vinculante para el texto. Con botones, normalmente solo desea enlazar al evento de clic.
Debido a esto, MvvmCross tiene algunos accesos directos, lo que le permite vincularse a un widget con-
especificando la propiedad que le interesa, y automáticamente seleccionará la mayor cantidad
uno apropiado
Eso es lo que estás viendo aquí. A diferencia del ejemplo de Android, estos enlaces
no son para una propiedad particular en la etiqueta y el campo de texto. En cambio, están obligados
directamente a los widgets, y seleccionan automáticamente la propiedad correcta para enlazar. En
En el ejemplo de Android, esto es menos fácil porque el enlace se expresó como un atributo
bute en el archivo XML, pero como estamos obligados a crear el enlace en código en iOS,
Podemos aprovechar esto.
También, a diferencia de Android, la definición de la propiedad en el modelo de vista ( .To (vm
vm.Hola) ) no parece ser una representación de cadena de la propiedad. En lugar,
Es una especie de función lambda que apunta a la propiedad. No hay nada real
magia aquí: utiliza esta expresión para obtener el nombre de la propiedad a la que enlazar
código. Si lo desea, puede establecer un valor de cadena de "Hola" en su lugar, pero al hacerlo
forma de obtener la finalización del código IntelliSense para ayudar a elegir la propiedad correcta y
el comprobador de apiladores si actualiza el nombre de una propiedad y olvida cambiarlo aquí. (Si tu
use las refactorizaciones incorporadas para cambiar el nombre de la propiedad, también se actualiza aquí auto-
matemáticamente)
Una vez que se crea este conjunto de enlace, lo aplica para enlazar los valores iniciales y escuchar
para actualizaciones Además de la sintaxis diferente, esto funciona de la misma manera que en Android:
los eventos en los controles de la interfaz de usuario hacen que el modelo de vista se actualice y se modifique la propiedad
los eventos del modelo de vista hacen que la vista se actualice.

ESTA SINTAXIS TAMBIÉN PUEDE UTILIZARSE EN ANDROID . Puede vincular Android en código en
exactamente de la misma manera que iOS si quieres. Los atributos en el diseño XML
son solo otra forma de hacerlo.

Ahora que has visto MVVM en acción con un ejemplo del mundo real, y entiendes
qué sucede en la aplicación, ampliemos nuestro ejemplo agregando algunas características más
tures, proporcionándole una exposición práctica a más trozos de MVVM.

4.2 4.2 Ampliando nuestra aplicación Hello World


En la tradición de las primeras aplicaciones típicas, vamos a cambiar nuestra aplicación Hello World para preguntar
para el nombre del usuario y luego salúdelos. Ya que esta es una aplicación móvil y nosotros
tener acceso a mucho más que una vieja consola aburrida, no mostraremos texto
para saludar: podemos hacer que la aplicación salude usando el texto a iOS y Android
motores de habla.
Estos son los pasos que vamos a seguir:

123
Ampliando nuestra aplicación Hello World 93

▪ Agregue un complemento multiplataforma de Xamarin para ayudar a conectarse al texto a


motores de habla en cada plataforma.
▪ Agregar un botón a la interfaz de usuario.
▪ Agregue código en nuestra capa multiplataforma que está conectada al botón para ejecutar el
motor de texto a voz.

4.2.1 Uso de complementos .NET Standard para acceder al código específico del dispositivo
Como ya has visto, queremos la mayor cantidad de código posible en las capas compartidas. los

https://translate.googleusercontent.com/translate_f 78/131
23/2/2020 Jim Bennett
El problema ocurre cuando queremos hacer algo específico del dispositivo, como obtener
nuestra aplicación para hablar usando un motor de texto a voz. El concepto es muy genérico: queremos
para llamar a un método de voz y hacer que lea las palabras a través de la salida de audio del dispositivo. los
La implementación, sin embargo, no es genérica. Android tiene una API para texto a voz, y así
iOS, pero las API no son iguales. Lo que necesitamos es una forma de llamar a un genérico
speak, y que la implementación se preocupe por la implementación específica de la plataforma
Mentaciones
Afortunadamente para nosotros, existe un patrón llamado cebo y interruptor . Qué
lo que podemos hacer es crear tres bibliotecas, cada una dirigida a una cosa diferente, una .NET Stan-
dard, uno específico de Android y uno específico de iOS. Estas bibliotecas tendrán lo mismo
nombres de ensamblaje, espacios de nombres y clases en cada uno. La única diferencia es la implementación
Mentación. La implementación de .NET Standard no hará nada, la de iOS sí
implementará la funcionalidad usando las API de iOS, y la de Android la implementará
utilizando las API de Android. Para usar estas bibliotecas, hacemos referencia a la versión .NET Standard
del proyecto .NET Standard, la versión de iOS del proyecto de iOS y el
Versión de Android del proyecto de Android.
En tiempo de compilación, el proyecto principal de .NET Standard se construye contra .NET Stan
implementación de la biblioteca, la aplicación de iOS contra la implementación de iOS, y
la aplicación de Android contra la implementación de Android. Cada biblioteca contiene lo mismo
espacios de nombres y clases, solo implementaciones diferentes. El tiempo de ejecución es donde la magia
sucede El compilador ve que los ensamblados tienen los mismos nombres y, en el exterior,
ponga el directorio al que hace referencia la aplicación "gana". Entonces, cuando estás compilando el iOS
aplicación, el directorio de salida final contendrá la versión del ensamblado al que se hizo referencia
creado por la aplicación de iOS en sí, la biblioteca de iOS con la implementación de iOS. por
Android es igual. Recuerde, estas bibliotecas tienen los mismos nombres de ensamblado, así que
solo uno puede estar en el directorio de salida. Cuando se ejecuta la aplicación y se realiza una llamada al
biblioteca, solo se puede resolver a la plataforma específica, ya que esa es la única versión
disponible. Esto significa que tanto el código de la aplicación como el proyecto central llamarán a la plataforma:
versión específica
La figura 4.9 muestra esto en acción en nuestro ejemplo de texto a voz. Las llamadas para hablar son
compilado contra el ensamblado al que se hace referencia, y en tiempo de ejecución la llamada real es
hecho a la versión a la que hace referencia el proyecto de la aplicación.

Page 124
94 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

1. Se agregan bibliotecas. Cada proyecto hace referencia 3. La implementación del estándar .NET
una biblioteca diferente que tiene el mismo ensamblaje de hablar no hace nada.
nombre, espacios de nombres y nombres de clase.
4. La implementación de la biblioteca de Android
2. La implementación de la biblioteca iOS de Speak de Speak usa el Android
usa las API de texto a voz de iOS. API de texto a voz.

¡Hola! ¡Hola!

Bibliotecas

iOS Estándar .NET Androide

Texto a voz Texto a voz Texto a voz


Hablar (cadena); Hablar (cadena); Hablar (cadena);

correr Compilar correr

Estándar .NET

iOS Androide
Utiliza .NET Standard
biblioteca en tiempo de compilación

Aplicación movil

5. En tiempo de ejecución solo en iOS, la biblioteca de iOS es 6. En tiempo de ejecución solo en Android, el Android
instalado: todas las llamadas a Speak utilizan iOS la biblioteca está instalada: todas las llamadas a Speak usan
versión independientemente de su procedencia la versión de Android independientemente de dónde
(aplicación iOS o biblioteca estándar .NET). vinieron de (aplicación de Android o .NET
Biblioteca estándar).

Figura 4.9 Uso de cebo y cambio con un complemento de texto a voz para compilar con un estándar .NET
versión y luego usar el código específico de la plataforma en tiempo de ejecución

Este es un patrón popular utilizado por una serie de paquetes NuGet multiplataforma. Xama-
Rin en sí mismo proporciona una serie de complementos (paquetes NuGet que proporcionan acceso al dispositivo)
funcionalidad específica usando el mismo patrón de cebo y interruptor. El examen de texto a voz
ple está tomado de uno de los complementos de Xamarin, y tienen otros complementos para acceder
otros servicios del dispositivo, como la cámara. La limitación con estos es que tienen que representar
reenviar el mínimo común denominador para que la funcionalidad funcione en todas las plataformas

https://translate.googleusercontent.com/translate_f 79/131
23/2/2020 Jim Bennett
formularios: no tiene
porque esto solo sentido agregar
está disponible funcionalidad
en iOS de cámara
y no funcionaría para fotos en vivo, por ejemplo,
en Android.

125
Ampliando nuestra aplicación Hello World 95

4.2.2 Instalar el complemento de texto a voz de Xamarin


Instalar este complemento es realmente fácil: lo hace utilizando el administrador de paquetes NuGet.
En Visual Studio para Windows, haga clic con el botón derecho en la solución en el Explorador de soluciones
y seleccione Administrar paquetes NuGet para la solución. Esto abrirá el paquete NuGet
gerente en el espacio de trabajo (figura 4.10). Seleccione Examinar, y en el cuadro de búsqueda ingrese
TextToSpeech . En la lista de paquetes que aparece, seleccione el etiquetado
"Xam.Plugins.TextToSpeech". La versión actual al momento de escribir es 3.0.1, entonces
seleccione esta versión de la configuración del paquete a la derecha (las versiones posteriores pueden funcionar, pero
para garantizar que el siguiente código funcione, use la versión 3.0.1). Seleccione todos los proyectos en el
lista de proyectos y haga clic en el botón Instalar en el lado derecho. Esto instalará el NuGet
paquete en los tres proyectos: el proyecto principal, la aplicación de iOS y la aplicación de Android.

En la pestaña Examinar usted La pestaña Consolidar muestra todos los paquetes


puede encontrar paquetes para que se usan en múltiples proyectos pero
instalar, ya sea navegando tener una versión diferente en esos proyectos.
La pestaña Actualizaciones
todos los paquetes (ordenados por muestra paquetes
popularidad) o mediante la búsqueda.con actualizaciones Por defecto, los paquetes provienen de
disponible. repositorio oficial en nuget.org. Usted puede
La pestaña Instalado cambiar esto a un repositorio interno o
muestra todos los paquetes un recurso compartido de archivos para usar otros paquetes NuGet.
instalado en el
solución.
Marca los proyectos
Donde quieras
para agregar el NuGet
paquete. Aquí nosotros
quiero agregarlo a
todos los proyectos

Haga clic en Instalar en


instalar el paquete
en el seleccionado
proyectos

Escriba aquí para buscar Elija una versión: la predeterminada Detalles del paquete: generalmente
El repositorio. es la última versión estable, incluir una URL del proyecto, que
pero seleccione 3.0.1. proporciona documentación sobre el uso.

Figura 4.10 Agregar el complemento TextToSpeech a todos los proyectos desde el administrador de paquetes NuGet

Page 126
96 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

Para Visual Studio para Mac, el proceso es similar pero un poco más largo: debe agregar el
Paquete NuGet para cada proyecto por separado. Haga clic derecho en el proyecto principal y seleccione
Agregar> Agregar paquetes NuGet. Desde el cuadro de diálogo que aparece (como se muestra en la figura 4.11),
busque "TextToSpeech", marque la casilla junto a Text to Speech Plugin para Xamarin
y Windows, seleccione la versión 3.0.1 del menú desplegable en la parte inferior derecha, y
haga clic en Agregar paquete. Repita este proceso para los proyectos de iOS y Android. Por suerte el
El administrador de paquetes NuGet muestra los paquetes que ya están en uso en la parte superior, por lo que después de agregar
para un proyecto, aparecerá en la parte superior de la lista para los otros proyectos.

Marca los paquetes Por defecto, los paquetes vienen Escriba aquí para buscar Detalles del paquete: generalmente
quieres instalar del repositorio oficial El repositorio. incluir una página de proyecto, que
(Puedes instalar en nuget.org. Tu puedes cambiar proporciona documentación
paquetes múltiples esto a un repositorio interno en uso
En seguida.) o un archivo compartido para usar otro
Paquetes NuGet.

https://translate.googleusercontent.com/translate_f 80/131
23/2/2020 Jim Bennett

Por defecto, solo estable Visual Studio pone cualquier Elija una versión: el Haga clic en Agregar paquete
Los paquetes están listados. Marque aquí
paquetes ya utilizados en el valor predeterminado es el últimopara
estable
agregar el paquete
para mostrar versiones preliminares. Su solución en la parte superior. versión, pero seleccione 3.0.1. a su proyecto

Figura 4.11 Agregar el complemento TextToSpeech a un solo proyecto desde Visual Studio para Mac Agregar paquetes
caja de diálogo

HAY UNA EXTENSIÓN PARA AYUDAR Hay una extensión para Visual Studio para
Mac llamó a NuGet Package Manager Extensions que proporciona un nivel de solución
gestión de paquetes. Esta extensión le permite instalar o actualizar paquetes
para múltiples proyectos al mismo tiempo.

Page 127
Ampliando nuestra aplicación Hello World 97

4.2.3 Agregar el código multiplataforma


Para agregar el código para pronunciar el mensaje de saludo, realice los cambios de código que se muestran a continuación.
bajando el listado a la clase FirstViewModel en FirstViewModel.cs en HelloCrossPlat-
Proyecto formWorld.Core. Este es el mismo lugar donde actualizaste el mensaje de saludo
capítulo 2. Este listado muestra la clase completa, no solo los cambios.

Listado 4.8 Actualizado FirstViewModel con código para hablar

Nuevas directivas de uso permiten


El constructor del modelo de vista toma
para usar ICommand y el
una instancia de ITextToSpeech
Interfaz ITextToSpeech de
interfaz como constructor
el complemento de texto a voz.
parámetro y lo almacena.
...
usando System.Windows.Input;
usando Plugin.TextToSpeech.Abstraction;

espacio de nombres HelloCrossPlatformWorld.Core.ViewModels


{ SayHelloCommand
clase pública FirstViewModel: MvxViewModel se configura una vez en
{ el constructor
solo lectura ITextToSpeech textToSpeech; y está conectado
al SayHello
FirstViewModel público (ITextToSpeech textToSpeech) método. Cuando el
{ el comando es
this.textToSpeech = textToSpeech; ejecutado, corre
SayHelloCommand = nuevo MvxCommand (SayHello); este método.
}

public ICommand SayHelloCommand {get; conjunto privado; } Este es un publico


nulo SayHello () solo lectura
propiedad para el
{
SayHelloCommand
textToSpeech.Speak ($ "Hola {Nombre}");
que la IU puede
}
unirse a.
nombre de cadena = "";
Nombre de cadena pública La propiedad Hello ha sido
{ renombrado a Nombre, y el
obtener {nombre de retorno; } campo de respaldo ha sido cambiado
set {SetProperty (nombre de referencia, valor); } de "hola" a "nombre".
}
}
}

El método SayHello hace una llamada al texto


interfaz de voz que se pasó a la
constructor para pronunciar el mensaje de saludo.

Estos son los cambios en el modelo de vista:


▪ Se ha agregado un parámetro constructor para tomar y almacenar una instancia de
Interfaz ITextToSpeech .
▪ La propiedad Hello existente y su campo de respaldo se han renombrado para que pueda

puede usarlos para almacenar el nombre del usuario.

https://translate.googleusercontent.com/translate_f 81/131
23/2/2020 Jim Bennett

Page 128
98 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

▪ Se ha agregado un nuevo método, SayHello . Este método hace una llamada al


Método Speak en la biblioteca de texto a voz estándar .NET (recuerde que en
tiempo de ejecución usará la implementación específica de la plataforma) usando una cadena construida
Del nombre . Esta llamada al método hará que su aplicación diga "Hola [Nombre]"
fuerte, utilizando el motor de texto a voz en el dispositivo.
▪ Se ha agregado una nueva propiedad de solo lectura llamada SayHelloCommand . En el
structor, este comando se crea como un MvxCommand , una clase que implementa
Iommand y proviene de MvvmCross. Esta clase de comando toma una acción como
un parámetro constructor, y cuando se ejecuta el comando, la acción es
invocado En este caso, la acción es una llamada al método SayHello .

Uno de los cambios más útiles e interesantes es la adición de un constructor.


parámetro que toma una instancia de ITextToSpeech . Pasar en una interfaz es genial
forma de mejorar tu código. Primero, estás segregado de la implementación de
la plataforma de texto a voz. Si desea utilizar una implementación diferente, usted
podría, siempre que implementara la misma interfaz. Segundo, y lo más importante,
puedes hacer una prueba unitaria de esto. Recuerde, la prueba es uno de los beneficios clave de usar un patrón
como MVVM, y hacer que el modelo de vista interactúe con la interfaz ITextToSpeech
en lugar de una implementación concreta le permite usar una implementación simulada en
las pruebas de su unidad, que pueden validar que se realizan las llamadas correctas. Sin esto, tu
no puede hacer una prueba unitaria, solo puede probar manualmente que se escuchó lo correcto al escuchar
para el texto hablado.
La pregunta obvia ahora es cómo pasar esta implementación al construc-
tor en tu aplicación. Has cambiado el constructor, pero ¿dónde cambias la llamada a
el constructor para agregar el nuevo parámetro? La respuesta es que no, al menos no
directamente. En su lugar, usa un poco de magia llamada inversión de control que puede crear
su modelo de vista para usted y pase lo correcto al constructor.

4.2.4 Inversión de control


Piensa en hacer café en casa. Necesita café, agua caliente, leche, azúcar y
alguna forma de maquinaria. Usted tiene el control del proceso de preparación del café.
en qué armario guarda su café, en qué parte del refrigerador vive la leche y cómo
para operar su técnica de café de elección (molinillo, prensa francesa, espresso
fabricante, o lo que sea). Usted tiene el control, pero eso significa que debe saberlo todo
(figura 4.12).
Ahora imagina que has decidido que es demasiado como el trabajo duro, así que en vez de eso, sales
a la cafetería local para obtener su taza de jugo de despertador por la mañana. De repente no
tiene que preocuparse por los frijoles, la leche, las teteras, las prensas francesas u otros artículos de café.
lia. En cambio, solo pide café y recibe una taza caliente de una sabrosa bebida con cafeína.
Ya no tienes el control, le has dado este control al barista (figura 4.13).
A cambio de esta falta de control, ahora tiene una manera fácil de obtener café. Tienes
invirtió ese control de usted a otra parte: podrían cambiar los frijoles o cambiar
su cafetera y no lo sabrías ni te importaría. Mientras consigas tu café,
estas feliz.

Page 129
Ampliando nuestra aplicación Hello World 99

Figura 4.12 Para preparar café en casa,


necesitas controlar todo.

café
Por favor

https://translate.googleusercontent.com/translate_f 82/131
23/2/2020 Jim Bennett

Figura 4.13 En una cafetería, usted


renunciar al control de la preparación del café

En código, podemos hacer lo mismo, como se muestra en la siguiente lista. Imagina un teo
clase retical que hace café en casa, y una clase de persona que lo usa.

Listado 4.9 Una clase que hace café

clase pública MakeCoffeeAtHome La clase de cafeteras


{
Public Coffee MakeCoffee ()
{
}
} Una clase que representa un
persona que necesita desesperadamente
Persona de clase pública café (como el autor)
{
público vacío WakeUp ()
{
var coffeeMaker = nuevo MakeCoffeeAtHome ();
Cuando el método WakeUp es
Bebida (coffeeMaker.MakeCoffee ()); llamado, la Persona construye un
} instancia de MakeCoffeeAtHome
y lo usa para hacer café

130
100 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

Vacío público Bebida (café, café)


{
}
}

En este listado hay una clase llamada MakeCoffeeAtHome que hace café, y una clase
Persona llamada que construye la cafetera y la llama para tomar café. Este código es
muy estrechamente acoplados: la clase Persona tiene el control completo de la preparación del café.
La desventaja es que la Persona tiene el control completo, lo que significa que, si algo
cambios, tendremos que cambiar la clase Persona . Por ejemplo, otro desarrollador podría
agregue un constructor a la clase MakeCoffeeAtHome para que se necesite un registrador para rastrear el
cantidad de café que se está bebiendo; si eso sucediera, este código se rompería. Del mismo modo, si
queríamos cambiar a comprar café en la cafetería local en lugar de hacerlo
nosotros mismos, tendríamos que reescribir nuestra clase de Persona . Otra consecuencia del código.
estar estrechamente acoplado es que no podemos hacer una prueba unitaria de la clase Person de forma aislada; podemos
solo pruébelo con la clase MakeCoffeeAtHome .
Sería mejor si pudiéramos invertir el control y hacer que sea responsabilidad de
algo más para construir la cafetera y pasarla a la Persona . Esto es mostrado
en el siguiente listado.

Listado 4.10 Cambio de persona para tomar una cafetera como argumento de constructor

Persona de clase pública La cafetera ya no está


{ construido por la persona.
MakeCoffeeAtHome coffeeMaker; En cambio, se pasa a la
Persona pública (MakeCoffeeAtHome coffeeMaker) constructor.
{
coffeeMaker = coffeeMaker;
}

público vacío WakeUp () La cafetera pasó


{ para el constructor es
Bebida (coffeeMaker.MakeCoffee ()); solía hacer café.
}
}

Esto es un poco mejor: hemos dejado de controlar la construcción de MakeCoffeeAtHome


clase, de modo que si la clase necesita cambiar su constructor, la clase Persona no
descanso. Avancemos un paso más en la siguiente lista y usemos una interfaz para que
La persona se vuelve más fácil de realizar pruebas unitarias.

Listado 4.11 Pasar una interfaz al argumento del constructor Persona

Interfaz pública IMakeCoffee


Una interfaz utilizada para
{ definir algo que
Coffee MakeCoffee (); puede hacer café
}

131
Ampliando nuestra aplicación Hello World 101

clase pública MakeCoffeeAtHome: IMakeCoffee

https://translate.googleusercontent.com/translate_f 83/131
23/2/2020 Jim Bennett
{ The MakeCoffeeAtHome
la clase implementa esto
Public Coffee MakeCoffee ()
interfaz.
{
}
}

Persona de clase pública A la clase Persona ya no le importa


{ sobre el tipo real de café
IMakeCoffee coffeeMaker; fabricante. Solo necesita algo que
Persona pública (IMakeCoffee coffeeMaker) implementa el IMakeCoffee para ser
{ pasó al constructor, y se
coffeeMaker = coffeeMaker; puede usar esto para hacer café.
}
}

Esto es mejor: tenemos una interfaz IMakeCoffee que se pasa a la clase Person . Nosotros
ahora puede realizar una prueba unitaria de la clase Person aisladamente burlándose de la interfaz. También podemos
ahora cambie de hacer café en casa a comprarlo en una cafetería sin
cambiando la clase de persona ; solo necesitamos una implementación diferente de IMakeCof-
interfaz de tarifa , como en el siguiente listado.

Listado 4.12 Una implementación diferente de la interfaz IMakeCoffee

clase pública CoffeeShop: IMakeCoffee


CoffeeShop también implementa el
{
Interfaz IMakeCoffee, entonces Persona
Public Coffee MakeCoffee () podría construirse usando esto,
{ y cuando hace café, el
} la cafetería lo estaría haciendo.
}

Hasta aquí todo bien. Hemos invertido el control de la cafetera en otro lugar, y esto
es una de las partes clave del patrón de diseño de inversión de control (IoC): renunciar a
control de cómo su código está conectado juntos. La pregunta ahora es dónde tiene este control
¿ido a? Pasar IMakeCoffee como parámetro de constructor está muy bien, pero
¿Qué va a hacer esto? ¿Dónde en el código llamamos a este constructor?
Lo que necesitamos es una caja mágica. Algo que podemos pedir para darnos una Persona y tenerla
crear la persona de forma automática. Todo lo que necesitaría saber es qué cafetera
utilizar. Podríamos decirle una vez que use una CoffeeShop cuando una instancia de IMakeCoffee es
necesitado, y cuando pedimos una Persona , creamos una usando Cof-
feeShop como el parámetro constructor. A la persona no le importa lo que se usa para
estructúrelo, solo que está construido con algo que implementa IMakeCoffee .
Una vez que le hemos dicho a la caja mágica que use una CoffeeShop , podemos dejar de pensar en cómo
para construir la Persona y solo tener uno creado para nosotros.
La buena noticia es que podemos usar una inversión del contenedor de control para hacer esto duro
trabaja para nosotros. Esta es una clase de contenedor que puedes considerar como la caja mágica. Tu lo dices
qué tipos tiene (esto se conoce como tipos de registro ) y cuándo solicita un
instancia de un tipo, mirará al constructor de ese tipo, creará todo lo que necesite,
y pásalos cuando construyas el tipo que querías. Esencialmente, inyecta el

Page 132
102 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

dependencia en tiempo de construcción, por lo que este concepto se conoce como inyección de dependencia
ción: utilizando una herramienta como un contenedor de IoC para insertar dependencias en una clase ya sea por
utilizando parámetros de constructor (inyección de constructor) o estableciendo propiedades después de
construcción. La figura 4.14 muestra esto.

CoffeeShop está registrado como


Solicite una instancia de Persona.
implementando IMakeCoffee.

Contenedor de IoC: ¡la caja mágica!

Cafetería Hago el café

Usuario

Persona
Persona
Persona pública
(IMakeCoffee mc)

El constructor de la persona necesita un IMakeCoffee. Viene una instancia de Persona


CoffeeShop implementa esta interfaz, por lo que un fuera, construido usando un
se pasa la instancia de CoffeeShop. instancia de CoffeeShop.

Figura 4.14 La caja mágica que es un contenedor de IoC: usted le dice qué tipos tiene y
cuando solicita una instancia de un tipo, cualquier dependencia se resuelve y luego se inyecta en
El constructor del tipo que ha solicitado.

Pensemos en esto en términos de nuestra aplicación Hello World. Si compila el código con
los cambios que hicimos en FirstViewModel , notará que se compila sin
problemas. Hemos agregado un nuevo parámetro de constructor, pero esto no rompe el código.

https://translate.googleusercontent.com/translate_f 84/131
23/2/2020 Jim Bennett
Esto se debe a que MvvmCross usa un contenedor IoC para todo lo que hace. Tu nunca
cree explícitamente una vista o un modelo de vista usted mismo; en cambio, confías en el incorporado
MvvmCross IoC container para hacerlo por ti. El código de inicio MvvmCross incorporado será
encuentre todos sus modelos de vista y regístrelos dentro del contenedor IoC, para que no
tengo que hacer algo con ellos. Recuerde el archivo App.cs con su llamado a Registrarse
NavigationServiceAppStart <ViewModels.FirstViewModel> () ? Esto le dice al Mvvm-
Marco cruzado que cuando la aplicación se inicia necesita hacer lo siguiente:
1 Cree este modelo de vista solicitándolo desde el contenedor.
2 Cree la vista correspondiente buscando una clase con el mismo nombre que la vista
modelo (pero con un sufijo Ver ).
3 Establezca el modelo de vista en la vista para que sea el modelo de vista del contenedor.
44 Mostrar la vista.

Page 133
Ampliando nuestra aplicación Hello World 103

Figura 4.15 La excepción lanzada cuando MvvmCross no puede resolver un tipo de su


Contenedor de IoC

Nuestro código se compila bien, pero ¿se ejecutará? No Si lo intentas, la aplicación lanzará un Mvx-
IoCResolveException , como se muestra en la figura 4.15.
El tipo MvxIoCResolveException nos dice que el marco MvvmCross era
incapaz de resolver un tipo del contenedor de IoC. El mensaje de excepción nos dice que
la excepción ocurrió al construir la clase FirstViewModel ya que no podía
encuentre una implementación de ITextToSpeech en el contenedor para usar como constructor
parámetro. Estos mensajes de excepción son bastante fáciles de depurar: indican claramente
qué tipo de parámetro falta y qué clase se estaba construyendo cuando falló
para encontrar el tipo
Esto es bastante fácil de solucionar: necesitamos registrar una instancia de esta interfaz con
el contenedor de IoC antes de crear el modelo de vista. El complemento de texto a voz tiene un
clase estática CrossTextToSpeech con una propiedad Current que devuelve una implementación
ción de la interfaz ITextToSpeech . Podemos registrar esto en el contenedor para que
Cada vez que se solicita esta interfaz, se devuelve esta instancia estática.
El lugar para hacerlo es dentro de la clase de aplicación multiplataforma, que vive en el
carpeta raíz del proyecto HelloCrossPlatform.Core en una clase llamada App dentro de un archivo
llamado App.cs. Esta clase de aplicación deriva de MvxApplication , una aplicación base de MvvmCross
clase que maneja la configuración de aplicaciones multiplataforma. El siguiente listado muestra el
cambio de código que necesita realizar en la clase de aplicación , así que continúe y actualice su código.

Listado 4.13 Agregar el registro del complemento de texto a voz a la clase de aplicación

usando MvvmCross.Platform;
Una nueva directiva de uso para dar
usando MvvmCross.Platform.IoC;
acceso a la IoC estática de Mvx
usando Plugin.TextToSpeech; envase

espacio de nombres HelloCrossPlatformWorld.Core Otro nuevo uso


{ directiva, que da acceso a
Aplicación de clase pública: MvxApplication
el complemento de texto a voz
{
anulación pública anular Initialize ()
{
Mvx.RegisterSingleton (CrossTextToSpeech.Current);
...
} El CrossTextToSpeech.Current
} instancia estática de ITextToSpeech
}
está registrado en el Mvx
contenedor como un singleton.

Page 134
104 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

Este cambio llama a RegisterSingleton en el contenedor Mvx , pasando la instancia estática


de la interfaz ITextToSpeech . RegisterSingleton le dice al contenedor que solo nosotros
Alguna vez quisiste una instancia de esta interfaz: cada vez que se solicita, siempre volverá
la misma instancia Cada vez que se crea nuestro modelo de vista, obtenemos un nuevo modelo de vista, pero
la misma instancia del complemento de texto a voz se pasa al constructor.
Ahora, cuando se inicia nuestra aplicación y se crea FirstViewModel , el contenedor
encuentre la instancia ITextToSpeech y páselo al constructor. Hemos invertido
control de cómo nuestro modelo de vista interactúa con el complemento de texto a voz al eliminarlo

https://translate.googleusercontent.com/translate_f 85/131
23/2/2020 Jim Bennett
desde el modelo de vista y ponerlo dentro de nuestro marco.

AVERIGUANDO CÓMO USAR UN PAQUETE DE PLUGIN O NUGET Cuando usa un


Paquete NuGet por primera vez, lo más difícil puede ser descubrir cómo
funciona y cómo usarlo. La mayoría de los buenos paquetes NuGet están documentados
en su propio sitio web o mediante un archivo Léame dentro del repositorio de GitHub para la fuente.
Generalmente hay un enlace a esta documentación que se muestra en el paquete NuGet
gerente. Para el complemento de texto a voz, los documentos están en GitHub en
https://github.com/jamesmontemagno/TextToSpeechPlugin.

Este es un patrón muy poderoso. MvvmCross registra cualquier modelo de vista derivado de
MvxViewModel como parte de su inicio predeterminado, y registramos ITextToSpeech
interfaz en el contenedor de forma manual. Como resultado, cada vez que se necesita el modelo de vista, es
creado con el parámetro constructor correcto. Al registrar todo lo que necesitamos a través de un
interfaz dentro de un contenedor de IoC, terminamos con un código débilmente acoplado. Esto no es solo
limitado a ver modelos, idealmente esto debería usarse también en su capa de modelo. Esta
le permite escribir fácilmente pruebas unitarias contra cualquier clase que desee, burlándose de todos los
caras como las necesitas.

IoC todas las cosas!


Otra cosa increíble a tener en cuenta es que no tiene que registrarse dentro de su
proyecto principal: puede registrarse fácilmente dentro de su código específico de plataforma. Esta
forma en que puede proporcionar acceso al código específico de la plataforma a través de una interfaz.

Un ejemplo popular de esto sería un servicio de diálogo, algo a lo que puede llamar para mostrar
un mensaje emergente para el usuario. Podría definir una interfaz para esto dentro de su núcleo
proyectar y crear dos implementaciones específicas de la plataforma, una en iOS y otra en
Androide. Cada implementación usaría el código específico de la plataforma relevante para mostrar
Un mensaje emergente.

Una vez que tenga la interfaz central y dos implementaciones específicas de la plataforma, puede
regístrelos dentro de la parte específica de la plataforma de la capa de aplicación. Además de
la clase MvxApplication multiplataforma, MvvmCross también tiene algunas plataformas
código de configuración específico derivado de MvxAndroidSetup en Android y MvxIosSetup en
iOS Puede encontrarlos dentro de los dos archivos Setup.cs, uno en la raíz del Android
aplicación, la otra en la raíz de la aplicación iOS, y allí puede registrar clases en el
Contenedor Mvx. En tiempo de ejecución, su proyecto principal hace referencia a la interfaz, y esto es
resuelto a la versión específica de la plataforma.

Page 135
Ampliando nuestra aplicación Hello World 105

Ahora que nuestro código central está configurado, agreguemos un botón a la interfaz de usuario, conéctelo a nuestro equipo
mand, y hacer que la aplicación realmente diga, "¡Hola!"

4.2.5 Conexión de la interfaz de usuario de Android


Hay dos pasos para conectar la interfaz de usuario de Android: primero, agregue un botón a la interfaz de usuario y
luego conéctelo para que coincida con los cambios que hemos realizado. Comenzaremos con la interfaz de usuario.
Comience abriendo el recurso FirstView.axml desde la carpeta de recursos de diseño
(figura 4.16). Para conectar los nuevos cambios, debe cambiar el enlace en
EditText y TextView para usar la propiedad Name renombrada y agregar un botón para hablar
"Hola." La siguiente lista muestra los cambios en los dos elementos dentro de Lineal-
Diseño y el nuevo elemento que necesita para el botón.

Figura 4.16 La estructura del diseño


carpeta dentro de la carpeta de recursos de la
Proyecto de aplicación de Android, que muestra la ubicación de
el archivo de diseño FirstView.axml

Listado 4.14 Los cambios dentro de LinearLayout desde la línea 20 en adelante

<LinearLayout
android: orientación = "vertical"
android: layout_width = "match_parent"
android: layout_height = "match_parent">
<Editar texto El enlace para EditText
android: layout_width = "match_parent" se cambia al nuevo nombre
android: layout_height = "wrap_content" propiedad.
android: textSize = "40dp"
local: MvxBind = "Nombre de texto" />
<TextView
android: layout_width = "match_parent"
android: layout_height = "wrap_content" El enlace para TextView
android: textSize = "40dp" se cambia al nuevo nombre
local: MvxBind = "Nombre de texto" />
propiedad.
<Botón
Este botón es nuevo y es
android: layout_width = "match_parent"
atado a lo nuevo
android: layout_height = "wrap_content"
Di hola, ordena que
android: textSize = "40dp"
acaba de agregar a su modelo de vista.
android: text = "Saluda"
local: MvxBind = "Haga clic en SayHelloCommand" />
</LinearLayout>

Cambiar de Hola a Nombre actualiza el enlace para buscar una propiedad en la vista

https://translate.googleusercontent.com/translate_f 86/131
23/2/2020 Jim Bennett
modelo llamado Nombre en lugar de uno llamado Hola . Esto coincide con el cambio de nombre que hemos
recien hecho.
El botón une algo llamado Click a algo llamado SayHelloCommand .
MvvmCross es lo suficientemente inteligente como para saber que Click es un evento, por lo que espera que esto sea
vinculado a un ICommand . En tiempo de ejecución cuando se toca el botón, se activa el evento Click
y se ejecuta Ejecutar en el comando.

Page 136
106 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

HAY UN DISEÑADOR QUE PUEDE USAR SI NO LE GUSTA XML La pestaña del diseñador es
solo eso: un diseñador visual para diseñar su interfaz de usuario. Puede usarlo para agregar el
botón: simplemente arrástrelo desde la barra de herramientas, y debería poder colocarlo
en LinearLayout debajo de los otros controles. Luego puede configurar el texto y
textSize en la ventana Propiedades y solo se sumerge en el XML para agregar el
Atributo MvxBind .

Si construyes y ejecutas esto (pero no construyas todo como lo harás


obtener un error de compilación para el proyecto de iOS que arreglaremos
más adelante), verá la nueva interfaz de usuario con el nuevo botón
(se muestra en la figura 4.17). Ingrese su nombre, toque el botón Diga
Hola, y suponiendo que tengas el volumen
apareció, oirás que la aplicación te saluda.
Cosas emocionantes, conseguir que una aplicación hable mediante uso compartido
código (a menos que esté en una cafetería llena de gente y
ahora todos te están mirando). Para demostrar que es compartido,
hagamos que iOS también nos hable.
Figura 4.17 La nueva aplicación de Android
con su botón Saludar
4.2.6 Cableado de la IU de iOS
Configurar la interfaz de usuario de Android es bastante fácil: simplemente agregue otro nodo al XML. Me encantaría
poder decir que iOS era igual de fácil, pero eso sería una mentira. iOS es un verdadero dolor
cuando se trata de la interfaz de usuario. Solía ser fácil cuando solo había una o dos pantallas
resoluciones, pero ahora que hay varios tamaños de pantalla de iPhone y iPad, es difícil.
Cuando solo había un tamaño de pantalla, todo se basaba en un concepto llamado
cuadros : establecería la ubicación exacta de píxeles y el tamaño de cada control (esencialmente
ing donde estaría el marco del control). Los primeros iPhones de retina también fueron
fácil: usaste los mismos "píxeles" y el sistema operativo simplemente duplicó todo. Ahora que hay
son algunas resoluciones y tamaños de pantalla más, todo usa algo llamado autolay-
fuera , donde especifica un conjunto de reglas llamadas restricciones para cada control, y el diseño es
calculado en función de estas reglas y el tamaño de la pantalla.
Por ejemplo, podría establecer una restricción que diga "hacer que mi botón use la mitad de la pantalla
ancho y se fijará al lado izquierdo a medio camino ". En cada tamaño de pantalla, el botón
estar en el mismo lugar en relación con la pantalla, en el lado izquierdo a medio camino, independientemente de
La altura de la pantalla. Esto hace que sea agradable
outs, pero establecer estas reglas puede ser doloroso. Voy a cubrir esto
con más detalle en el capítulo 11, así que por ahora solo siga estos
Instrucciones "simples" para obtener un nuevo botón en la pantalla.
Abra el archivo FirstView.storyboard desde iOS
Carpeta Vistas del proyecto (figura 4.18). Hablaremos de sto-
Figura 4.18 La estructura de
ryboards con más detalle en el capítulo 11, pero por ahora piense
la carpeta Vistas en la aplicación iOS
como diseñador visual para tu vista. Esto mostrará el proyecto, que muestra la ubicación de
ver como un gran cuadro blanco que muestra la entrada de texto el guión gráfico de FirstView

trol y etiqueta.

137
Ampliando nuestra aplicación Hello World 107

Cuando se abra el diseñador, vaya a la caja de herramientas. En Visual Studio para Mac, esto
debería aparecer como una almohadilla con pestañas en el lado derecho. Si no está allí, puede abrirlo usando
Ver> Almohadillas> Caja de herramientas. En Visual Studio para Windows, debe estar acoplado a la izquierda.
Si no está allí, puede mostrarlo usando Ver> Caja de herramientas.
Escriba el botón en la barra de búsqueda en el cuadro de herramientas y arrastre un botón hasta debajo del texto
control de entrada, como en la figura 4.19.

Haga clic aquí para ingresar al modo de edición de restricciones

https://translate.googleusercontent.com/translate_f 87/131
23/2/2020 Jim Bennett

Figura 4.19 Arrastrando un botón al guión gráfico

Una vez que el botón esté allí, haga clic en el botón Modo de edición de restricciones para ingresar a un modo donde
Puedes establecer las restricciones. Esto cambiará el resaltado para que tenga un conjunto de I-bar han-
dles alrededor del botón en lugar de las manijas circulares. Esto se muestra en la figura 4.20.

Botón

Botón

Estas manijas de barra en T Estas manijas de barra en I


se utilizan para establecer el espacio se utilizan para configurar
para los cuatro bordes Este mango cuadrado se usa para configurar anchura y altura.
Centro horizontal o vertical.

Figura 4.20 Los manejadores de restricción para restringir el tamaño, la distancia a otros controles y
alineación central

Page 138
108 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

Una vez que estos controladores están visibles, puede arrastrarlos para crear las restricciones. Como tu
arrástrelos, verá varios widgets en la vista iluminados o resaltados con
líneas puntedas. Estas son guías que muestran lo que puede restringir las propiedades de
botón para. Esencialmente, estas restricciones le permiten fijar la posición del botón, su
tamaño, o su punto central en relación con otros widgets, o en relación con la pantalla. La altura-
las luces en pantalla le muestran a qué puede configurar esa restricción particular.
Para que su botón se vea bien y se ubique debajo del campo de texto para todos los tamaños de pantalla,
tendrás que restringir tres cosas: la parte superior del botón, su ancho y su horizonte
centro tal:
1 Arrastre el asa superior de la barra en T (la que parece una T muy corta en la parte superior
el medio) sobre el cuadro de entrada de texto. La parte superior, media e inferior del texto.
el cuadro de entrada y la etiqueta se convertirán en líneas verdes discontinuas, con la que el mouse
está sobre resaltado en azul. Suelta la barra T en la línea discontinua más baja de
el cuadro de entrada de texto. Esto establece una restricción superior de una cierta distancia desde el bot-
Tom del cuadro de entrada de texto. No se preocupe por el valor de esta distancia por ahora.
2 Arrastre el tirador de la barra I más inferior (el que parece una I en su lado o un
H aplastado, no el que parece una T invertida) en la entrada de texto
cuadro de arriba. Cuando haga esto, la pantalla se volverá azul y los otros controles
será verde Cuando lo arrastre sobre el cuadro de entrada de texto, se volverá azul y
el resto de la pantalla estará verde; este es el momento de soltar el botón del mouse
o trackpad. Esto establece una restricción de ancho para que coincida con el ancho del cuadro de entrada de texto.
3 Arrastre el asa cuadrada en el medio del botón al centro de la pantalla
ancho, justo debajo del botón. La pantalla cambiará de modo que el contorno del
otros controles son líneas verdes discontinuas, con otras dos líneas verdes discontinuas hacia abajo
el centro horizontal y el centro vertical de la vista. Déjalo caer en el
línea verde por el centro horizontal. Esto limitará la mitad de la
botón a la mitad de la pantalla.

La figura 4.21 muestra estos pasos.


Cuando haya terminado, el botón tendrá un resaltado naranja, como se muestra en la figura
ure 4.22. Esta es la manera del diseñador de decirle que el botón estará en un lugar diferente
en tiempo de ejecución. Puede solucionar esto diciéndole al diseñador que coloque el control en función de
restricciones Para hacer esto, salga del modo de edición de restricciones haciendo clic en Edición de cuadros
Botón de modo (el primer botón en la sección de restricciones), luego actualice los cuadros
usando el botón Actualizar restricciones desde marcos (el último botón en las restricciones
sección). El botón que ha agregado debe cambiar su tamaño para que tenga el mismo ancho que la entrada de texto.
caja, sentado un poco debajo de ella.
Las restricciones mismas se mostrarán en la pestaña Diseño del panel Propiedades,
que se puede mostrar en Visual Studio para Mac usando Ver> Pads> Propiedades si no es
ya se muestra en el lado derecho. En Windows está en la ventana Propiedades, que
debe estar acoplado en el lado derecho, pero si no puede visualizarlo usando Ver> Apropiado-
corbatas Ventana. Estas pestañas muestran las reglas de diseño aplicadas. El espacio superior al texto

https://translate.googleusercontent.com/translate_f 88/131
23/2/2020 Jim Bennett

Page 139
Ampliando nuestra aplicación Hello World 109

1. Arrastre desde la barra en T superior hasta


línea discontinua inferior en el campo de texto.

La línea discontinua pasará de verde


a azul cuando el cursor está sobre él.
Esto establece la restricción superior. Ancla
la parte superior del botón hacia abajo
del campo de texto con espaciado fijo
entre ellos.

2. Arrastre la barra I inferior hacia el centro.


del campo de texto.
Portador 23%
La pantalla se pondrá verde a medida que la arrastre,
el campo de texto se volverá azul cuando el
y el cursor está sobre él. (Los colores son
eliminado aquí para mayor claridad.)

Esto establece la restricción de ancho. Dice


el botón siempre debe tener el mismo ancho
como el campo de texto.

3. Arrastre el asa del cuadrado central sobre


la línea discontinua vertical en el centro
de la vista.
Esto establece la posición horizontal
restricción, diciéndole al botón que
siempre tiene su centro en el centro
de la pantalla.

Figura 4.21 Los tres pasos para configurar las restricciones: establecer la restricción superior, la restricción de ancho,
y la restricción central horizontal.

Haga clic en el botón Actualizar marcos basados en restricciones para actualizar


el diseñador y muestra cómo se verá en tiempo de ejecución.

Antes de actualizar marcos Después de actualizar marcos

Figura 4.22 Diseñe las restricciones y haga clic en el botón Actualizar marcos para que coincida con las restricciones para ver
cómo se verá la vista en tiempo de ejecución.

140
110 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

el campo se establece en un valor constante, el ancho del botón se establece en el ancho del texto
campo y el centro horizontal del botón se establece en el centro de la supervista:
esa es la vista que lo contiene (en este caso, toda la pantalla).
Si siguió las instrucciones anteriores, debería tener restricciones como esas
se muestra en la figura 4.23. El valor en la restricción Top Space To puede ser diferente de
el 14 que se muestra en la figura porque este valor depende de dónde dejó caer el botón-
ton, pero el resto debería ser igual. Si el suyo no coincide, la solución más fácil es eliminar
el botón e intente nuevamente.

Use la pestaña Diseño para ver las restricciones.

La parte superior del botón está limitada a 14 puntos.


(en este caso) desde la parte inferior del campo de texto.

El ancho del botón está restringido a


ancho del campo de texto.

El centro X (centro horizontal) está restringido

https://translate.googleusercontent.com/translate_f 89/131
23/2/2020 Jim Bennett
al centro de la Supervista: la vista
que contiene este control

Figura 4.23 Las restricciones que se muestran en el panel Propiedades

Una vez que se define el diseño, puede establecer el texto y el nombre del botón en
Ficha de widgets del panel Propiedades. Establezca la propiedad Nombre en la sección Identificar en "Diga-
HelloButton "y la propiedad Título en la sección Botón para" Saludar ". Establecer el
el título actualiza lo que se muestra en el botón; establecer el nombre creará una propiedad en el
código subyacente para ese botón. Puede ver estos valores establecidos en la figura 4.24.
Atemos ahora este nuevo botón en la vista al comando en FirstView-
Modelo en nuestro proyecto principal. Si abre FirstView.cs y busca en ViewDidLoad
método, verá el código que une la propiedad original Hello a los widgets de la interfaz de usuario.
Realice los cambios en la siguiente lista para vincular los controles existentes al nuevo Nombre
y para conectar el botón a SayHelloCommand .

141
Ampliando nuestra aplicación Hello World 111

Use la pestaña Widget para ver


Las propiedades del widget.

Si ingresa un nombre aquí, un


nueva propiedad será creada
en FirstView.designer.cs
archivo con ese nombre y con
El tipo UIButton.

Establecer el texto para mostrar


en el botón aquí

Figura 4.24 Configuración de las propiedades del widget para el botón

Listado 4.15 Se actualizó el método ViewDidLoad , vinculando las nuevas propiedades y el botón

anulación pública void ViewDidLoad () La etiqueta está vinculada a


{ su nueva propiedad de nombre.
base.ViewDidLoad ();

var set = this.CreateBindingSet <FirstView, FirstViewModel> ();


set.Bind (Label) .To (vm => vm.Name);
set.Bind (TextField) .To (vm => vm.Name);
El TextField es
set.Bind (SayHelloButton) .To (vm => vm.SayHelloCommand); atado a tu
set.Apply (); nuevo nombre
} El nuevo UIButton llamado propiedad.
SayHelloButton está obligado a
tu nuevo SayHelloCommand.

Al igual que con UITextField y UILabel , MvvmCross tiene algunos conocimientos sobre UIButton :
El tipo subyacente de un botón en iOS. El evento estándar al que te conectarás en un
UIButton es TouchUpInside , por lo que, de manera predeterminada, este evento está vinculado al comando. Usted puede
anule esto si lo desea, especificándolo explícitamente, pero en este caso desea el valor predeterminado,
así que no necesitas dar un nombre de evento.
Y eso es todo, no hay lógica como tal porque todo está en el proyecto central.
Solo hay nuevos bits de interfaz de usuario y algunos enlaces. Si ejecuta esto ahora, ingrese su nombre y
toca el botón Saludar, ¡oirás que tu aplicación te saluda!

Página 142
112 C APÍTULO 4 Hola de nuevo, MVVM: comprender y mejorar nuestra sencilla aplicación MVVM

https://translate.googleusercontent.com/translate_f 90/131
23/2/2020 Jim Bennett
Una cosa para notar con el texto a voz es que cuando haces la llamada para hablar,
vuelve inmediatamente y la IU no está bloqueada mientras la aplicación está hablando. Puedes probar
esto editando el texto mientras la aplicación está hablando. Desafortunadamente, esto no siempre es el
case: es muy fácil llamar a un método en su comando que tarda mucho tiempo en ejecutarse
(como acceder a un servicio web), y si no tiene cuidado, su IU no responderá
durante esta llamada Peor aún, el sistema operativo podría finalizar su aplicación si no responde
Sive por mucho tiempo. Discutiré esto con más detalle y veré cómo puede manejar múltiples
hilos completos en sus aplicaciones en el próximo capítulo.

Resumen
En este capítulo aprendiste que
▪ Las aplicaciones MvvmCross se crean utilizando las diferentes capas de MVVM y MvvmCross
tiene código para cada capa, como el modelo de vista base y los tipos de comando, bind-
ing, y soporte para ver-modelo-primera navegación.
▪ Los complementos pueden proporcionar una funcionalidad adicional específica del dispositivo a sus aplicaciones que es accesible
Sible de su código multiplataforma.
▪ La inversión del control es un gran patrón que le permite definir un acoplamiento flojo
entre clases, lo que facilita cambiarlas sin romper las existentes
código y hacer que las clases sean más fáciles de probar por unidad.
▪ Tener una aplicación móvil que te hable con solo unas pocas líneas de código multiplataforma es
¡realmente genial!

También aprendiste a
▪ Encuentre y agregue complementos fácilmente utilizando el administrador de paquetes NuGet.
▪ Agregue nuevos controles a una interfaz de usuario de Android haciendo cambios simples en un archivo XML
(aunque puedes usar el diseñador).
▪ Agregue nuevos controles en iOS y colóquelos usando restricciones a través de
diseñador, dando un diseño de interfaz de usuario realmente agradable a costa de la complejidad.
▪ Conecte fácilmente los controles a su modelo de vista mediante encuadernación, permitiendo lo mismo
código que se llamará desde widgets de IU tanto en iOS como en Android.

Page 143

55
¿Qué estamos esperando (a)? Un
introducción a multihilo
para aplicaciones Xamarin

Este capítulo cubre


▪ ¿Qué es un hilo y qué es multihilo?
▪ Qué es el hilo de la interfaz de usuario y por qué es especial
▪ Uso de tareas para ejecutar código en subprocesos en segundo plano
▪ Usar async y esperar para hacer su código más limpio

https://translate.googleusercontent.com/translate_f 91/131
23/2/2020 Jim Bennett

Al crear aplicaciones, siempre desea brindar a sus usuarios la mejor experiencia posible.
El mundo de las aplicaciones móviles es altamente competitivo, con usuarios de aplicaciones dispuestos a abandonar su
aplicación para un competidor si les ofreces una mala experiencia. Hay muchas maneras de
proporcionar esta mala experiencia, pero una de las peores es tener una aplicación con un retraso lento
Ging UI, o uno que se bloquea y deja de responder. Afortunadamente, arreglando aplicaciones
ese retraso o bloqueo es relativamente fácil, y en este capítulo veremos formas de hacerlo.
Este capítulo se sumerge en el código multiproceso para aplicaciones móviles, que cubre el
UI thread, Task y async / await . Si eres un desarrollador experimentado de C # UI

113

Page 144
114 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

(tal vez de años de creación de aplicaciones WPF de escritorio), ha utilizado tareas antes, y si es que todas
su código usa asíncrono y espera , puede saltarse este capítulo. Si tu experiencia
La presencia de código multiproceso no está basada en la interfaz de usuario, o no está en C #, ¡entonces sigue leyendo! Existen
Hay algunas peculiaridades a tener en cuenta al escribir interfaces de usuario que usan múltiples hilos, y hay
algunas herramientas increíbles en la caja de herramientas de C # que pueden ayudar.

5.1 ¿Por qué necesitamos código multiproceso?


Piense en una aplicación de correo electrónico (algo que probablemente use de manera regular). Esta aplicación
muestra sus correos electrónicos actuales y, a medida que los usa, se enviarán a su proveedor de correo electrónico
y descargue cualquier correo electrónico nuevo. Todo esto sucede a la perfección: la interfaz de usuario de la aplicación es
receptivo en todo momento, lo que le permite leer y eliminar mensajes al mismo tiempo que
la aplicación está buscando o enviando nuevos correos electrónicos.
Esta es una buena experiencia de aplicación, y algo que la mayoría de los usuarios de aplicaciones dan por sentado.
Las aplicaciones descargarán datos sin interrumpir lo que estás haciendo como usuario, tal vez dando
dar algunos comentarios para mostrarle que está haciendo algo en segundo plano, o mostrar
ing algunos datos ficticios mientras se inicia la aplicación. La figura 5.1 muestra algunos ejemplos de esto.

Buscar Buscar Buscar

Noticias La gente viaja Noticias La gente viaja Noticias La gente viaja

Cargando…

Lauren Ipsum
Auckland

Amar la playa hoy!

Publicado hace 4 horas Cargando…

Aarti Effem
Wellington

Afuera para comer

Publicado hace 5 horas

Lauren Ipsum
Auckland

Datos de carga ficticios Diálogo de progreso en la parte superior Diálogo de progreso sobre
de la lista siendo recargada toda la pantalla

Figura 5.1 Aplicaciones que realizan operaciones en segundo plano, como la carga de datos, generalmente
tener algún tipo de indicador que muestre que algo está sucediendo.

LOS USUARIOS PUEDEN NOTIFICAR CUALQUIER COSA MÁS DE 100-200 EM Los estudios han
hecho en lo que los usuarios perciben como un retraso notable, y han descubierto que
Cualquier cosa que supere los 100–200 ms se notará como un breve retraso. Microsoft ahora
recomienda que todo lo que tarde más de 200 ms se haga en la parte posterior
tierra, y han seguido esta filosofía en el marco .NET, haciendo
cualquier cosa más larga que esa asíncrona. Google y Apple recomiendan algo por mucho tiempo.
más de 100 ms se ejecutan en segundo plano. Puedes leer más sobre esto en

Page 145
¿Por qué necesitamos código multiproceso? 115

El artículo de Jakob Nielsen "Tiempos de respuesta: los 3 límites importantes" en el


Sitio web de Nielsen Norman Group: www.nngroup.com/articles/response-times-
3-límites-importantes / .

Es posible que también hayas visto aplicaciones que no brindan una experiencia tan agradable y se bloquean
la interfaz de usuario por un corto tiempo. Si lo bloquean durante demasiado tiempo, es posible que haya matado la aplicación
usted mismo, o en el caso de Android visto un buen diálogo que ofrece matarlo en su
favor. Esto es algo que nosotros, como desarrolladores de aplicaciones, queremos evitar.

https://translate.googleusercontent.com/translate_f 92/131
23/2/2020 Jim Bennett
El principio básico es simple: mantén la pantalla y los widgets funcionando mientras estás
cargando datos en segundo plano. Pero ¿qué significa esto? ¿Qué es "el fondo"?
y ¿cómo podemos nosotros, como desarrolladores de aplicaciones, cargar datos de esta manera?
Comencemos por echar un vistazo rápido al problema antes de ver la solución. por
a modo de ilustración, veremos nuestra aplicación Hello Cross-Platform World de
capítulo 4. En esta aplicación, vinculamos un comando en el modelo de vista a un botón, para decir
hola al usuario Pero supongamos que antes de que la aplicación pueda saludar al usuario,
necesita hacer una llamada a un servicio web para hacer algo.
Hacer una llamada a un servicio web desde una aplicación móvil puede ser lento, especialmente en caso de un pobre
conexión celular (recuerde, millones de usuarios de teléfonos inteligentes se basan en el desarrollo
mundo operativo, donde las velocidades de red son mucho más lentas que las 4G que algunos países
tener). Cambiaremos nuestro código para llamar a un método que no hace nada durante unos segundos, para
simule esta larga llamada a un servicio web.
Realice el siguiente cambio en FirstViewModel , dentro del archivo FirstViewModel.cs en
el proyecto HelloCrossPlatformWorld.Core.

Listado 5.1 Agregar un método de larga duración para simular una llamada de servicio web lenta

usando System.Threading.Tasks;
Una nueva directiva de uso permite
clase pública FirstViewModel: MvxViewModel el código para usar Tarea en el
{ Nuevo método.
...
nulo SayHello () En el método SayHello, el código llama a
{
nuevo método MakeLongWebServiceCall para
MakeLongWebServiceCall ()
simular una llamada de servicio web de larga duración.
textToSpeech.Speak ($ "Hola {Nombre}");
}
El nuevo método que simula
vacío MakeLongWebServiceCall () la larga llamada al servicio web
{
Task.Delay (TimeSpan.FromSeconds (5)). Wait ();
Espera 5 segundos (no
} preocuparse demasiado por cómo
} esto funciona, lo veremos
más adelante en este capítulo).

Realice este cambio y ejecute la aplicación (ya sea en iOS o Android). Si toca el botón Diga
Hola, verás que toda la aplicación se bloquea durante cinco segundos antes de saludar a
tú. Si escribe en el cuadro de texto, no pasará nada durante esos cinco segundos; el texto
solo aparecerá después de que hayan transcurrido los cinco segundos. Si se trataba de un cliente de correo electrónico y se bloqueó

Page 146
116 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

durante tanto tiempo mientras descarga un correo electrónico, sería una experiencia muy mala.
Si eso sucedió mientras un usuario intentaba eliminar el correo electrónico actual, y nada sucedió
cuando tocaron el botón Eliminar, podrían tocarlo una y otra vez, y
de nuevo. Una vez que la aplicación vuelve a responder, estos toques múltiples pueden convertirse en
múltiples eliminaciones, eliminando demasiados correos electrónicos. No es una buena experiencia.
Llevemos esto un poco más lejos e imaginemos que nuestra aplicación necesita hacer muchas llamadas a
este servicio web, que lleva aún más tiempo. Cambia el tiempo de espera a 60 segundos usando el código
en la siguiente lista y ejecute esto en Android (no iOS esta vez).

Listado 5.2 Incrementando el tiempo de espera a 60 segundos

vacío MakeLongWebServiceCall () El intervalo de tiempo es ahora


{ aumentado de 5 segundos
Task.Delay (TimeSpan.FromSeconds (60)). Wait (); a 60 segundos.
}

No solo su aplicación no responderá durante mucho tiempo, sino que el sistema operativo intervendrá
y decirle al usuario que la aplicación no responde, preguntándole si quiere esperar o
cierre la aplicación (figura 5.2).

Figura 5.2 En Android, si una aplicación


bloquea durante mucho tiempo, se le dice al usuario
y dado la opción de esperar a que
volver a responder o cerrarlo.

La mayoría de los usuarios tocarán Aceptar en este punto para cerrar la aplicación. Si esto sucede con demasiada frecuencia, pocos

https://translate.googleusercontent.com/translate_f 93/131
23/2/2020 Jim Bennett
los usuarios volverán a su aplicación. En su lugar, descargarán y usarán la aplicación de un competidor.
Solo Android ofrece esta opción: en iOS, la aplicación simplemente se bloquea.
En el ejemplo de la aplicación de correo electrónico, los correos electrónicos se descargan en segundo plano mientras
La aplicación aún es utilizable. Lo ideal sería que quisiéramos hacer lo mismo en nuestra aplicación, nuestra
Una llamada al servicio web debe realizarse en segundo plano para que la aplicación permanezca
sensible.

Page 147
¿Qué son los hilos? 117

Pero, ¿qué queremos decir cuando decimos que queremos que las cosas sucedan en segundo plano ?
¿Cómo podemos usar este "fondo" para ejecutar el código? La respuesta está en el mundo de
hilos y código multiproceso.

5.2 ¿Qué son los hilos?


Como usuarios habituales de aplicaciones, todos hemos visto cosas que suceden en segundo plano: tweets
descarga mientras leemos otros tweets y correos electrónicos que aparecen mientras escribimos
ing nuevos correos electrónicos. Probablemente hayas oído hablar de hilos y código multiproceso, pero qué
Qué significan estos términos? Antes de analizar cómo podemos hacer que nuestras aplicaciones sigan respondiendo
mientras realiza largas llamadas de servicio web, veamos qué es realmente un hilo.

5.2.1 Comprando cafe


Imagina que sales a comprar café para tu equipo en el trabajo y vas muy despacio,
cafetería ineficiente que solo tiene una persona trabajando en ella. Haces cola y
cuando es tu turno, le das tu orden al barista, un café a la vez. Tu orden
un café, el barista lo hace, usted ordena el siguiente, el barista lo hace, usted ordena el
siguiente, y así sucesivamente. Una vez que tiene sus cafés, paga por ellos. Terminas
de pie allí por mucho tiempo aburriéndote, y finalmente obtienes tus cafés o
te vas. De cualquier manera, no estás contento porque te fuiste de la oficina por
mucho tiempo (y tal vez aún menos feliz porque te aburriste esperando y no terminaste)
con cualquier café a cambio de sus esfuerzos). No eres solo tú, la gente detrás de ti
en la cola también podría aburrirse y salir antes de que incluso lo hayan ordenado (figura 5.3).

Un montón de
café
Por favor

Figura 5.3 Cuando espera un pedido grande de café en una cafetería mal administrada, es posible que simplemente
Ríndete antes de tomar tu café.

Veamos una línea de tiempo de cómo podría suceder esto, como se muestra en la figura 5.4. Como puedas
mira, hay muchas esperas para preparar cada café antes de que finalmente puedas
paga y toma tus cafés. Usted ordena, espera, ordena, espera, ordena, espera ...
¿Cómo podría mejorar la cafetería? Lo primero que podrían hacer sería tomar
su pedido por adelantado, luego prepare sus cafés y luego lo llame una vez que hayan terminado. Tú
haga su pedido, deje su nombre y tenga tiempo para leer las noticias o navegar

148 de 1189.
118 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

Pregunta por Obtener Pregunta por Obtener Pedir más


Espere Espere Pagar
latté latté blanco plano blanco plano café...

Haz mas Tomar


Hacer café con leche Hacer blanco plano
café... dinero

Hora

Figura 5.4 Ordenar un café a la vez y prepararlo, luego pedir otro toma mucho tiempo.

La Internet. Luego, cuando sus cafés estén listos, el barista gritaría su nombre
y recogerías tus cafés. La figura 5.5 muestra la línea de tiempo de este enfoque.

https://translate.googleusercontent.com/translate_f 94/131
23/2/2020 Jim Bennett
Esto es un poco mejor: todavía lleva la misma cantidad de tiempo obtener sus cafés,
pero al menos no estás tan aburrido como antes, y es menos probable que te des por vencido y te vayas
antes de tomar tu café. Sin embargo, esto no es mejor para el resto de la cola. Aquellos
las personas pobres y sedientas tendrán que esperar el mismo tiempo por una sabrosa bebida con cafeína.
¿Qué más podría hacer la cafetería? ¿Qué tal agregar más personas? Si ellos
empleado otro barista, el café podría hacerse un poco más rápido. Un barista podría
tomar el pedido, y el otro podría hacer el café. La figura 5.6 muestra la línea de tiempo para
Este mejor escenario.
Esto no lo hace mejor para nosotros, pero lo hace un poco mejor para la otra costumbre.
ers: ahora pueden ordenar mientras se prepara nuestro café, y también pueden salir y
hacer otras cosas mientras esperan. Es mejor porque los clientes no esperan en la cola.
aburrido por tanto tiempo, pero todavía se necesita la misma cantidad de tiempo para preparar el café de todos.
Vamos a intentar mejorarlo agregando baristas adicionales, como se muestra
en la figura 5.7. Esto es aún mejor: no solo todos los clientes pueden hacer sus pedidos
y luego hacer lo que quieran, en lugar de hacer cola, pero múltiples cafés
se puede hacer al mismo tiempo, lo que significa que cada cliente obtiene su café más rápido.

Orden Recoger
Tiempo libre haciendo otras cosas. Pagar
todo café

Tomar Hacer Llamada Tomar


Hacer café con leche Hacer blanco plano
orden Más café... nombre dinero

Hora

Figura 5.5 Si puede hacer su pedido de café por adelantado, puede hacer otras cosas mientras se prepara.

Page 149
¿Qué son los hilos? 119

Orden
todo

Orden Recoger
Tiempo libre haciendo otras cosas. Pagar
todo café

Tomar Tomar Llamada Tomar


Tiempo libre haciendo otras cosas.
orden orden nombre dinero

Hacer
Hacer café con leche Hacer blanco plano
Más café...

Hora

Figura 5.6 Tener dos baristas significa que uno puede tomar pedidos mientras que el otro hace café.

Orden Recoger
Tiempo libre haciendo otras cosas. Pagar
todo café

Orden Recoger
Tiempo libre haciendo otras cosas. Pagar
todo café

Tomar Tomar Llamada Tomar Llamada Tomar


Tiempo libre haciendo otras cosas.
orden orden nombre dinero nombre dinero

Hacer
Hacer café con leche
Más café...

Hacer
Hacer blanco plano
Más café...

Hacer
Hacer espresso
Más café...

Hora

Figura 5.7 Tener varios baristas para hacer café significa que los pedidos se pueden hacer más rápidamente.

https://translate.googleusercontent.com/translate_f 95/131
23/2/2020 Jim Bennett

Page 150
120 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

Este es un gran modelo para una cafetería, y casualmente un gran modelo para el software.
también.

5.2.2 Entonces, ¿qué es un hilo?


Puede pensar en los miembros del personal en la cafetería como hilos diferentes, cada uno
está trabajando en una cosa separada al mismo tiempo. Tienen una serie de tareas que hacer, y
los hacen en orden (un hilo, como un barista, solo puede hacer una cosa a la vez). Cuando
no tienen nada que hacer, simplemente se quedan ahí sin hacer nada, esperando algo
más que hacer.
En términos informáticos, un subproceso es un subproceso de ejecución, una forma para que una aplicación se divida
el código se está ejecutando en una o más tareas que se ejecutan simultáneamente. Cuando una aplicación
se ejecuta, se ejecuta utilizando al menos uno, pero generalmente más subprocesos. Cada aplicación, ya sea
La aplicación móvil, la aplicación de escritorio, la aplicación de consola o el sitio web se ejecuta en al menos un hilo. Solo como un
una cafetería sin personal no podría hacer café, no hay forma de que
código para ejecutarse sin un hilo.
Una aplicación de correo electrónico tendrá un hilo para la interfaz de usuario, que ejecutará la interfaz de usuario
código que permite al usuario interactuar con una lista de correos electrónicos, toque uno para leerlo, escriba una respuesta,
o realizar otras tareas que el usuario quiera hacer, como se muestra en la figura 5.8. También tendrá
uno o más hilos de fondo para hablar con el proveedor de correo electrónico, descargando
correos electrónicos o enviando los que acaba de escribir. Estos subprocesos de fondo solo interactuarán
Rompa el hilo que ejecuta la interfaz de usuario cuando sea necesario, como cuando un nuevo correo electrónico tiene

1. Todas las interacciones del usuario son manejadas rápidamente por el hilo de la interfaz de usuario,
ya que no está ejecutando ninguna acción de larga duración.

Desplazarse Abierto Cerca


correos electrónicos correo electrónico correo electrónico

UI Actualizar mostrar mostrar Actualizar


hilo monitor correo electrónico lista de correo lista de correo

Antecedentes
Encuesta para nuevos correos electrónicos
hilo

Hora

2. El hilo de fondo es responsable 3. Cuando se descarga un correo electrónico, el fondo


para acciones de larga duración como cargar el hilo interrumpe el hilo de la interfaz de usuario el tiempo suficiente
correos electrónicos del proveedor de correo electrónico.
para que la IU se actualice para mostrar los nuevos correos electrónicos.

Figura 5.8 En una aplicación de correo electrónico habrá un subproceso de interfaz de usuario que mantiene la interfaz de usuario receptiva y un fondo
hilo para descargar correos electrónicos.

Page 151
¿Qué son los hilos? 121

se ha descargado y la lista de correos electrónicos debe actualizarse. Piense en una aplicación de correo electrónico como
el servidor en nuestro ejemplo de cafetería, pero sirviendo correos electrónicos en lugar de café. los
los baristas corren en segundo plano buscando correos electrónicos en lugar de bebidas,
enviándolos, haciendo las tareas necesarias y solo interrumpiendo el servidor
cuando lo necesiten (como avisar al servidor cuando un correo electrónico ha estado inactivo)
cargado, en lugar de cuando un café está listo).
Esta división del trabajo en múltiples hilos no es algo que sucede automáticamente.
cally Debe indicarle explícitamente a su aplicación que use varios subprocesos, de la misma manera que
una cafetería tiene que emplear a varios baristas para hacer café. Multihilo es el término
que describe el código que usa múltiples hilos para manejar su carga de trabajo. Nuestro cafe ideal
la tienda es multiproceso: tiene varios baristas (hilos) que crean café al mismo tiempo
tiempo (ejecutando código al mismo tiempo).

Múltiples hilos no siempre significan que suceden múltiples cosas a la vez


Si tiene dos subprocesos que ejecutan código, este código puede o no ejecutarse en el
Mismo tiempo.

Su dispositivo móvil probablemente tenga un procesador multinúcleo, lo que significa que tiene un chip
que puedes considerar como más de un chip pegado. Puede tener dos bits
de código ejecutándose al mismo tiempo al tener múltiples núcleos ejecutando código diferente
un núcleo ejecuta un hilo y uno ejecuta el otro.

Además, sin embargo, puede ejecutar múltiples subprocesos en el mismo procesador dando uno

https://translate.googleusercontent.com/translate_f 96/131
23/2/2020 Jim Bennett
hilo un poco de tiempo de procesamiento, y luego pausarlo y darle al otro hilo algo
tiempo de procesador Es inteligente, así que si un hilo tiene que esperar algo, como leer
desde la red, puede usar ese tiempo de espera para ejecutar el otro hilo.

Si te sientes geek y quieres aprender más, Google "multitarea preventiva".

5.2.3 Un resumen rápido


Tomemos un momento rápido para revisar todo esto, ya que es algo importante:
▪ Todo el código se ejecuta en un subproceso, y un subproceso ejecuta el código en secuencia.
▪ Una aplicación puede tener varios subprocesos, cada uno con un código diferente al mismo tiempo
hora.

Esto suena simple, pero el diablo está en los detalles. Enhebrar es en realidad un tema masivo
(con términos aterradores como mutexes , semáforos y secciones críticas ), digno de un libro en su
derecho propio. Afortunadamente para nosotros, los programadores de C #, no necesitamos preocuparnos demasiado por
Estos detalles. Pero hay algunos conceptos básicos que necesitará conocer, y algunos
construcciones de lenguaje para aprender sobre eso encapsulan todo lo difícil, permitiéndonos
desarrolladores para subir y escribir código.
Lo que realmente necesita saber son los dos tipos diferentes de hilos (UI y
subprocesos de fondo), tareas y async / wait . Comencemos con los dos tipos de hilos.

Página 152
122 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

5.3 Subproceso de interfaz de usuario e hilos de fondo


En nuestra cafetería, tenemos dos tipos diferentes de empleados: un servidor que interactúa
con el cliente y los baristas que toman instrucciones del servidor y hacen café
cuota. En nuestro ejemplo de aplicación de correo electrónico, hay dos tipos de hilos: uno que ejecuta el usuario
interfaz (UI) y una o más que realizan operaciones en segundo plano, como
recuperar correos electrónicos. Todas las aplicaciones móviles son iguales a la aplicación de correo electrónico, y tienen estos dos tipos
de los hilos. Estos tipos de hilos, como los dos tipos de empleados de cafeterías, son actu-
Aliado muy distinto y con características muy diferentes.

5.3.1 El hilo de la interfaz de usuario


El hilo de la interfaz de usuario es algo de lo que escuchas mucho cuando construyes aplicaciones
con una interfaz de usuario Es el hilo principal dentro de su aplicación (a menudo escuchará la interfaz de usuario
hilo conocido como el hilo principal ): el servidor en el mostrador que toma su café
orden. Al comprar café, solo interactúa con una persona que toma su pedido
y te llama cuando tu café está listo, y es lo mismo con el hilo de la interfaz de usuario. Cuando
su usuario interactúa con la interfaz de usuario de su aplicación, interactúa con la interfaz de usuario
hilo. Si ese servidor está ocupado haciendo otra cosa, no puede interactuar con ellos para
pedir café hasta que estén libres. Lo mismo ocurre con el hilo de la interfaz de usuario: si está ocupado, no puede
haz cualquier otra cosa en ese hilo hasta que esté libre.
El subproceso de la interfaz de usuario tiene un trabajo simple pero importante: ejecutar la interfaz de usuario. Sus
responsable de todo lo que hace la interfaz de usuario. Si escribe una letra en un cuadro de texto, la IU
thread detecta la pulsación de tecla, ejecuta el código para dibujar el nuevo personaje en la pantalla,
y plantea el evento de cambio de texto. Si actualiza un control, el hilo de la interfaz de usuario es responsable
ble para actualizar la pantalla, incluido el cálculo de cómo deben establecerse los controles y
lo que debe mostrarse El hilo de la interfaz de usuario ejecuta animaciones, transiciones entre vistas y
muestra ventanas emergentes. Cada interacción con el usuario a través de la pantalla y cada cambio en el
la pantalla es manejada por este hilo.
Nunca necesita crear el subproceso de interfaz de usuario: el SO lo crea para usted cuando su
la aplicación se inicia y permanece activa hasta que se cierra la aplicación.
Un barista solo puede hacer una cosa a la vez. Si una cafetería tiene un solo barista que
prepara un café a la vez, el cliente tiene que esperar a que se prepare cada café. En
Del mismo modo, un hilo solo puede hacer una cosa a la vez. Ejecuta sus tareas secuencialmente, por lo que
el hilo no puede hacer la siguiente tarea hasta que se complete la tarea anterior, incluso si una tarea
lleva mucho tiempo (figura 5.9).
El subproceso de interfaz de usuario funciona utilizando una cola de mensajes que procesa en orden, y
Estos mensajes pueden provenir del sistema operativo o de su código. Cuando tocas un control
o escriba texto, el sistema operativo lo detecta, crea un mensaje y lo envía al hilo de la interfaz de usuario. los
La cadena de interfaz de usuario maneja el mensaje cuando termina con los mensajes anteriores en
su cola
Esto es bastante fácil de demostrar: inicie Hello Cross-Platform modificado
Aplicación mundial que cambiaste anteriormente en este capítulo, ingresa un texto, toca el botón Saludar
e ingrese más texto mientras la aplicación no responde. Prueba esto en iOS, o si

Page 153
Subproceso de interfaz de usuario e hilos de fondo 123

https://translate.googleusercontent.com/translate_f 97/131
23/2/2020 Jim Bennett

Toque un Ver interfaz de usuario Entrar Ver texto Hacer más


Espere Espere
botón actualizar texto cambio cosas...

Encargarse de
Hacer algo Actualiza el cuadro de texto
más cosas...

Hora

Figura 5.9 El subproceso de la interfaz de usuario maneja la entrada del usuario secuencialmente, por lo que debe terminar de manejar uno
entrada antes de que pueda manejar otro.

prefiero hacerlo en Android reducir el tiempo de espera de 60 segundos a unos 20 segundos


para evitar el mensaje de advertencia del sistema operativo. Verá que la interfaz de usuario se bloquea durante el tiempo de espera, y
a medida que escribe, no aparecerá nada en la pantalla. Cuando la espera haya terminado, de repente
ver que todo lo que ha escrito aparece en el cuadro de texto.
Cuando toca el botón, el sistema operativo genera un mensaje, que es
luego manejado por el hilo de la interfaz de usuario, generando el evento click (figura 5.10). Este evento fue
enlazado a un comando definido usando una Acción , lo que significa que la Acción también se ejecuta en
el hilo de la interfaz de usuario. Nuestra acción se detuvo durante unos segundos, lo que significa que el hilo de la interfaz de usuario también
hizo una pausa por unos segundos. Durante esos segundos, la interfaz de usuario no respondía totalmente
porque estaba ocupado en la pausa. Solo puede hacer una cosa a la vez, así que si está ocupado, espere
ing, no puede responder a los mensajes del sistema operativo en respuesta a la entrada del usuario. Cada-

Grifo Entrar Ver texto


Espera: la interfaz de usuario no responde
botón texto cambio

Mensaje Toque de botón Presionar tecla


cola mensaje mensaje

UI Actualizar el
El evento de hacer clic en el botón ejecuta un comando de ejecución prolongada
hilo caja de texto

Hora

Figura 5.10 El hilo de la interfaz de usuario maneja los mensajes del sistema operativo que resultan de las interacciones del usuario,
y si tarda demasiado en manejar un mensaje, la interfaz de usuario parece no responder.

Page 154
124 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

Lo que tiene que ver con la interfaz de usuario tiene que esperar. Una vez que se acabe el tiempo y termine el comando,
la interfaz de usuario puede continuar procesando el siguiente mensaje en su cola.

SI UN BOTÓN NO FUNCIONA, LOS USUARIOS LO TOCARÁN HASTA QUE FUNCIONE Si una aplicación se congela,
es probable que los usuarios golpeen los botones o el teclado varias veces hasta que la aplicación
responde, lo que lleva a que su aplicación maneje todos estos eventos cuando el hilo de la interfaz de usuario es
liberado. Esto podría conducir a un comportamiento de la aplicación que el usuario no espera, si
toca un botón Eliminar en un cliente de correo electrónico y la aplicación no responde, podrían
tóquelo varias veces más y termine eliminando más correos electrónicos de los que esperaban.

El subproceso de la interfaz de usuario dura tanto como su aplicación, y su aplicación solo dura mientras la interfaz de usuario
hilo. Si se lanza una excepción dentro del hilo de la interfaz de usuario y no se maneja, el hilo
finaliza y su aplicación muere. Por ejemplo, en una aplicación de correo electrónico, si hay una conexión a
no se puede establecer el servidor y se lanza una excepción en el subproceso de la interfaz de usuario y no se cuelga
dled correctamente, la aplicación moriría. Obviamente esto no es algo bueno. Conduce a un sim-
regla completa: no permita excepciones no detectadas en el hilo de la interfaz de usuario.
En los capítulos anteriores, vimos las capas de MVVM, y la interfaz de usuario encaja muy bien
mucho en la capa de vista. Los hilos, sin embargo, no encajan en estas capas simples y agradables:
Pueden abarcar todas las capas. Puede ejecutar código en el hilo de la interfaz de usuario que comienza en la vista (como
como en un clic de botón), luego ejecuta código en la capa de modelo de vista (como el comando
que maneja el clic), que luego realiza una llamada a la capa del modelo. El código en
cada capa se ejecutará en el hilo de la interfaz de usuario. Si este código es rápido (menos de 100–200 ms), esto
no es un problema, pero idealmente cualquier cosa más lenta no debería estar en el hilo de la interfaz de usuario, pero debería
en su lugar, ejecútelo en un subproceso en segundo plano para eliminar cualquier retraso o bloqueo obvio en la interfaz de usuario.

5.3.2 Subprocesos de fondo


El subproceso de la interfaz de usuario es el único subproceso que ejecuta la interfaz de usuario. Hilos de fondo,
Por otro lado, hay hilos que realizan tareas en segundo plano, como down-
cargando correos electrónicos. Estos son nuestros baristas: el servidor les da algo que hacer,
y se apagan y lo hacen, solo interrumpen el servidor cuando lo necesitan, como después

https://translate.googleusercontent.com/translate_f 98/131
23/2/2020 Jim Bennett
Los cafés están hechos. Del mismo modo, puede disparar hilos de fondo desde su
UI, y estos se disparan y hacen lo suyo, solo interrumpiendo el hilo de la UI si es necesario,
como cuando se descarga un correo electrónico y la interfaz de usuario necesita actualizarse para mostrar esto.
A diferencia del hilo de la interfaz de usuario, los hilos de fondo se pueden crear, ejecutar código y morir con:
matando a la aplicación. Si un hilo de fondo está bloqueado haciendo algo, la aplicación
permanece receptivo Si tarda varios minutos en descargar su correo electrónico, nada se bloquea
en su aplicación (y no se muestran mensajes desagradables en Android preguntando al usuario si
quieren cerrar la aplicación).
Además, a diferencia del subproceso de la interfaz de usuario, debe crear explícitamente subprocesos de fondo en su
código. Afortunadamente para nosotros como desarrolladores de C #, esto no es tan difícil como podría pensar, y una vez
De nuevo sigue el modelo de nuestra cafetería.

155 de 1189.
Usar tareas para ejecutar código en segundo plano 125

5.4 Usar tareas para ejecutar código en segundo plano


Hasta ahora hemos establecido que le pides café al servidor, y luego los baristas hacen
eso. Profundicemos un poco más en esto.
Usted ordena una cantidad de cafés, y el servidor toma el pedido y escribe cada artículo
abajo en un boleto. Estas entradas se pasan a los baristas que realmente manejan
ellos, generalmente fijándolos a una tabla. Cada boleto representa una tarea para los baristas
hacer, por ejemplo, preparar café, té o calentar un panecillo. Los baristas manejan
estas tareas una por una, y una vez que terminan, ponen el artículo en el mostrador para que
el servidor puede ver que el pedido está progresando y luego llamarte una vez que todo está
hecho. El servidor crea tareas; los baristas manejan estas tareas y le avisan al servidor
cuando terminen
Este modelo funciona para un barista, dos baristas, tres, cuatro ... tantos como usted tenga
espacio para (figura 5.11). Los propios baristas también podrían crear tareas para otras personas,
como la persona que lava los platos, gritándoles para pedir más
tazas cuando se ponen bajas. El barista continúa haciendo café mientras el lavavajillas está
preparando las tazas limpias, para que nadie esté esperando. Los baristas incluso podrían asignar tareas a los
servidor, como pedirles que verifiquen un pedido, interrumpiendo la capacidad del servidor para
actuar con los clientes mientras completan la tarea que se les ha encomendado.
También puede pensar en una aplicación de correo electrónico como algo que crearía tickets entre
Finalmente para rastrear el trabajo a realizar. Por ejemplo, una vez que se carga la aplicación, creará un ticket
para descargar una lista de correos electrónicos nuevos que serán manejados por algo. Una vez que esta lista es
descargado, puede crear tickets para descargar el contenido completo de cada nuevo correo electrónico.

1. El servidor escribe tickets para todos los 2. El primer barista recoge el


cafés que deben hacerse y primer boleto y se le asigna la tarea
se los pasa a los baristas. de hacer un café con leche.

Hacer
Entradas latté

Latté
Orden dos Tomar
cafés orden
Plano
blanco

Hacer
blanco plano

3. El segundo barista recoge el


segundo boleto y se le asigna la tarea
de hacer un blanco plano.

Figura 5.11 Cuando ordena café del servidor, le dan a los baristas diferentes tareas para
hacer, como hacer un café con leche o un blanco plano.

Page 156
126 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

En C # puede crear "tickets" y anclarlos al equivalente .NET del tablón de anuncios


para que algo pueda recogerlos y ejecutarlos. Estos tickets se denominan tareas y
los entrega un programador de tareas para que se ejecute en un subproceso en segundo plano o
el hilo de la interfaz de usuario.

5.4.1 Tarea y Tarea <T>

https://translate.googleusercontent.com/translate_f 99/131
23/2/2020 Jim Bennett
En nuestra
servidor. Encafetería
el marcohay tareas
.NET que sehay
también asignan
tareas,a baristas o lavavajillas
representadas por una oclase llamada Tarea
(que vive en el espacio de nombres System.Threading.Tasks ). Esta clase es similar a una
comando en que envuelve una acción que se puede ejecutar. A diferencia de un comando, estas acciones
solo se puede ejecutar una vez, y no se activan por una acción del usuario sino por una tarea programada:
uler que desencadena la acción en un hilo apropiado. También hay Tarea <T> , que
envuelve un func que devuelve una instancia de T . Esto se usa si necesita obtener un valor de retorno
de su tarea, como una lista de correos electrónicos descargados de un servidor de correo electrónico.
Cuando un servidor crea un boleto para una taza de café, el próximo barista disponible
tome este boleto y prepare el café (esto es como una Tarea <T> con un valor de retorno de un
taza de cafe). La programación de la preparación del café es manejada por la junta que marca
Las cosas se fijan en: los baristas toman el próximo boleto disponible y comienzan a preparar el café.
Si cada café toma la misma cantidad de tiempo, los baristas terminarán tomando
boletos por turnos, pero si un café toma más tiempo que otro, un barista podría terminar
tomar dos o tres boletos seguidos antes de que el otro barista termine de hacer el
café más lento y está disponible para recoger un boleto.
En este ejemplo, el pin board es un programador de tareas. Las tareas se crean contra un par-
planificador de tareas ticular, y este planificador los ejecuta en el hilo relevante. Por
por defecto, las tareas usan un planificador que ejecuta las tareas en un hilo de fondo (veremos
otro programador de tareas más adelante en este capítulo). El programador de tareas predeterminado tiene un grupo de
subprocesos en segundo plano y utiliza el siguiente disponible para ejecutar la siguiente tarea, tal como
El próximo barista disponible recoge el próximo boleto de café. Esto abstrae muchas cosas
aplicaciones, incluida la creación y gestión de subprocesos. No tienes que hacer nada
usted mismo: el programador de tareas lo hace todo por usted.
Puede crear una tarea simplemente actualizando una instancia y pasándole una acción a
ejecutar como el parámetro constructor Para la tarea <T> , le pasa un Func <T> . Una vez que es-
Ated, puede llamar a Start () para ejecutarlo. La tarea incluso tiene un método de fábrica estático, Ejecutar , que
toma una Acción o Func <T> como parámetro, crea la Tarea o la Tarea <T> y la ejecuta
automáticamente. Por defecto, todas estas nuevas tareas se ejecutarán en un subproceso en segundo plano porque
usan el programador de tareas predeterminado (figura 5.12).
Anteriormente en este capítulo modificamos la aplicación Hello Cross-Platform World para esperar un
poco tiempo antes de hablar, para simular una llamada de servicio web de larga duración. Esta bloqueado
arriba de la interfaz de usuario, así que cambiemos el código para usar una Tarea para ejecutar la llamada larga en la parte posterior
suelo. Realice los cambios de código que se muestran en la siguiente lista y ejecute la aplicación.

Page 157
Usar tareas para ejecutar código en segundo plano 127

1. Las tareas se crean utilizando el 2. El programador de tareas asigna 3. Las tareas se ejecutan en múltiples
planificador de tareas predeterminado.
las tareas para la próxima disponible hilos de fondo.
hilo de fondo.

Ir a buscar

Tareas correo electrónico

Ir a buscar
correo electrónico
Crear Tarea
Tareas planificador
Enviar nuevo
correo electrónico

Enviar nuevo
correo electrónico

Figura 5.12 El programador de tareas toma tareas y las ejecuta en el hilo apropiado.

Listado 5.3 Mantener la interfaz de usuario receptiva mediante el uso de una tarea

nulo SayHello ()
{
var task = new Task (() => MakeLongWebServiceCall ());
task.Start ();
La tarea La llamada existente a
Está empezado. MakeLongWebServiceCall es
textToSpeech.Speak ($ "Hola {Nombre}");
convertido a una acción y se pasa
}
al constructor de la tarea.

Si toca el botón Saludar ahora, verá que la aplicación sigue respondiendo durante
la espera. También escucharás que la aplicación te saluda de inmediato.
En este código, está creando una Tarea que utilizará el programador de tareas predeterminado, por lo que
ejecutar en un hilo de fondo, y le está pasando una Acción para ejecutar. El llamado a comenzar
le indicará al programador de tareas que comience a ejecutar esta tarea en segundo plano. Esta llamada
vuelve inmediatamente, no espera a que se complete la tarea . La construcción de la
La tarea ocurre en el hilo de la interfaz de usuario (recuerde, el comando que llama a SayHello se llama
desde un toque de botón, que se maneja en el hilo de la interfaz de usuario), pero la ejecución ocurre en
el fondo, por lo que el resto del método se ejecuta de inmediato (figura 5.13).
Podemos simplificar el código usando el método estático Task.Run , que envuelve el contenido
estructura y lo inicia en una llamada, como se muestra en la siguiente lista.

https://translate.googleusercontent.com/translate_f 100/131
23/2/2020 Jim Bennett
Listado 5.4 Crear una nueva tarea y ejecutarla, en lugar de usar el método de Inicio
nulo SayHello ()
{
Task.Run (() => MakeLongWebServiceCall ());
Task.Run es lo mismo
textToSpeech.Speak ($ "Hola {Nombre}");
como crear una tarea y
}
llamando a Start.

Page 158
128 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

Grifo Oír
botón palabras

UI Crear Decir
hilo tarea Hola

Tarea Calendario
planificador tarea

Antecedentes
Ejecutar tarea
hilo

Hora

Figura 5.13 La ejecución de una tarea ejecuta su código en un subproceso en segundo plano.

Este es un patrón agradable, pero ¿y si quisiéramos que la aplicación saludara después del largo método?
ha terminado? Por ejemplo, en una aplicación de correo electrónico, querríamos un código que iría al
proveedor de correo electrónico y descargar correos electrónicos, y una vez que se descargan, le dirá al
usuario, en el verdadero estilo de Tom Hanks / Meg Ryan, que tienen correo. Si el mensaje llegó
antes de descargar los correos electrónicos, tendría un usuario de aplicación infeliz.
Nuevamente, como desarrolladores de C # podemos hacer esto fácilmente, usando continuaciones de tareas.

5.4.2 Encadenamiento de tareas


Supongamos que uno de nuestros baristas necesita tazas limpias y más granos de café, con el
las tazas son más urgentes: solo tienen dos tazas, pero suficientes frijoles para cinco más
tazas de café. Podrían pedirle a un lavaplatos que los consiga a ambos, uno tras otro:
algunas tazas limpias y luego obtener más frijoles. La tarea de buscar más tazas es lo primero,
y una vez que está completo, el lavavajillas puede recoger más frijoles (figura 5.14).
En una aplicación de correo electrónico, nos gustaría hacer algo similar: primero, la aplicación iniciaría sesión,
luego descargaría una lista de todos los correos electrónicos nuevos, y luego comenzaría a descargar-
ing el contenido de los nuevos correos electrónicos. Todas estas tareas tienen que suceder en orden (después de todo,
la aplicación no puede descargar el contenido de los correos electrónicos antes de saber qué correos electrónicos nuevos
obtener contenido para) y deben suceder en segundo plano para que la interfaz de usuario permanezca
sensible.
Podemos hacer esto con nuestras tareas en código: cree una tarea para ejecutar algún código y dígale
que una vez que se completa, se debe ejecutar otra tarea para ejecutar otro código. Esto es
gracias a un método en Tarea - Continuar con . Este método toma una Acción <Task> como

Page 159
Usar tareas para ejecutar código en segundo plano 129 129

Pregunta por Pide frijoles


Tazas Frijoles
tazas después de tazas

Conseguir tazas Conseguir frijoles

Hora

Figura 5.14 Las tareas se pueden encadenar, como pedirle a un lavavajillas que traiga más tazas y
luego traiga más granos de café.

https://translate.googleusercontent.com/translate_f 101/131
23/2/2020 Jim Bennett
su parámetro
como y devuelve
la original unacompletado,
tarea se ha nueva Tareaypara ejecutardeesa
el original acción.
tareas Estaa nueva
se pasa tarea
la acción comienza
como su tan pronto
parámetro. Si la tarea original era una Tarea <T> , ContinueWith tomaría un
Acción <Tarea <T>> como su parámetro. En esta acción, puede agregar el código que desea
ejecutar después de que se complete la tarea. Esto a menudo se conoce como continuación de la tarea .
Podemos usar esto en nuestra aplicación de ejemplo para saludar al usuario después de la larga ejecución
El método se ha completado. La siguiente lista muestra el código para esto, así que haga esto
cambiar y ejecutar la aplicación

Listado 5.5 Después de que una tarea se haya completado, puede comenzar a ejecutar otra tarea

nulo SayHello ()
Continuar con toma un
{
Acción <Task>, pasando el
Task.Run (() => MakeLongWebServiceCall ())
Tarea en la que se convocó
.ContinueWith (t =>
en la acción La acción
{ aquí contiene el código para
textToSpeech.Speak ($ "Hola {Nombre}"); saludar al usuario.
});
}

Como se esperaba, la aplicación saludará al usuario después de un retraso (no dude en ajustar el
retraso en MakeLongWebServiceCall a algo así como 5 segundos para acelerar su espera-
tiempo de ing). Durante este retraso, la aplicación seguirá respondiendo porque todo está bien.
escribiendo en un hilo de fondo, gracias al programador de tareas predeterminado.
Al igual que la Tarea <T> , ContinueWith también puede crear una tarea con un valor de retorno, por lo que puede
devuelve Tarea <T> en lugar de solo Tarea . Para hacer esto, en lugar de pasar una Acción <Task>
o Acción <Tarea <T>> , puede pasar una Func <Tarea, T> o Func <Tarea <T>, TResult> .
Estas continuaciones, al igual que las tareas, pueden tener un valor de retorno, pero se ejecutan en la parte posterior.
suelo.
¿Cómo obtenemos el valor de retorno de una tarea si no es como un método que devuelve un
¿valor? Podemos obtener de la tarea del resultado .

160 de 1189.
130 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

5.5 Resultados de tarea


En nuestra cafetería, algunas tareas tienen un resultado que vuelve al creador de la tarea,
y algunos no. Si un barista tiene la tarea de preparar café, el resultado es una taza de café
pasado de nuevo al servidor. Si un lavaplatos se encarga de limpiar el piso, hay
No hay resultado para devolver.
Las tareas en C # son las mismas, y puede establecer el tipo de resultado mediante el uso de un argumento de tipo
ment. La tarea no tiene resultado y es como el lavaplatos trapeando el piso. La tarea <T> tiene un
resultado del tipo T y es como el barista haciendo café. Este resultado solo está disponible una vez
la tarea está terminada; no puede tomar una taza de café antes de que el barista lo haya hecho.
Una aplicación de correo electrónico podría crear una tarea para descargar una lista de todos los correos electrónicos nuevos que necesitan
para ser descargado Esta lista podría devolverse en el resultado de la tarea, y sería
iterado en otras tareas para descargar el contenido de cada correo electrónico.
Hay tres formas de obtener el resultado de una tarea: seguir encuestando para ver si ha terminado,
forzar la tarea a esperar, o usar una continuación.

5.5.1 Sondeo para ver si la tarea ha terminado

Puede sondear periódicamente la Tarea <T> , verificando la propiedad IsCompleted , y si es


Es cierto , la tarea ha finalizado y puede obtener el resultado (figura 5.15).

UI Terminado Terminado Terminado Terminado Obtener


hilo ¿todavía? ¿todavía? ¿todavía? ¿todavía? resultado

No No No si

Antecedentes
Encuesta para nuevos correos electrónicos
hilo

Hora

Figura 5.15 Las tareas se pueden sondear continuamente para ver si han terminado.

Esto no siempre es ideal, ya que necesita ejecutar código para realizar el sondeo. Esta técnica no es
utilizado a menudo.

5.5.2 Esperando la tarea

La tarea tiene un método llamado Esperar que bloquea hasta que finaliza la tarea, y puede llamar
esto para forzar su código a esperar hasta que la tarea haya finalizado, como se muestra en la figura 5.16. Esta
a menudo no es ideal, ya que anula el propósito de ejecutar tareas mediante el uso de código de bloqueo, pero
A veces es útil. Es algo que debe evitarse en el hilo de la interfaz de usuario, por supuesto,
o terminarás con una aplicación que no responde.
Un buen ejemplo del uso de este enfoque sería cuando se precargan datos, como un
correo electrónico. Una aplicación de correo electrónico podría cargar rápidamente el remitente y los detalles del asunto de todos los correos electrónicos nuevos
y luego inicie una tarea para cargar el contenido de cada correo electrónico. Si se descarga el correo electrónico

https://translate.googleusercontent.com/translate_f 102/131
23/2/2020 Jim Bennett

Page 161
Resultados de tarea 131

UI Crear Servir Espera con un Encargarse de


hilo tarea tarea IU que no responde ... resultado

Tarea Calendario Tarea


planificador tarea terminado

Antecedentes
Ejecutar tarea
hilo

Hora

Figura 5.16 La espera en una tarea se bloquea hasta que la tarea haya finalizado

antes de que el usuario lo toque para ver los contenidos, la aplicación solo puede mostrar los contenidos. Si
el correo electrónico no se ha descargado completamente, la aplicación podría mostrar un diálogo de progreso mientras llama
Espere en un subproceso de fondo (para que la interfaz de usuario siga respondiendo). Una vez que el correo electrónico esté completamente
descargado, el Esperar llamada devolverá y la aplicación puede mostrar el contenido del correo electrónico.

HA VISTO ESPERAR ANTES Esperar puede sonar familiar porque lo hemos usado
antes de. En el método MakeLongWebServiceCall en los ejemplos que hemos estado
trabajando, hubo una llamada en espera: Task.Delay (Time-
Span.FromSeconds (5)). Esperar (); .
Task.Delay es un método de fábrica que crea y devuelve una nueva tarea que
no hace nada más que esperar un período de tiempo (en la primera versión de este método,
Esto fue 5 segundos). La llamada a Esperar se bloquea hasta que esta nueva tarea finalice, así que
hasta que transcurran los 5 segundos de retraso.
Task.Delay puede ser útil si desea que algo se ejecute después de un período fijo
de tiempo, como sondear nuevos correos electrónicos cada minuto.

5.5.3 Obteniendo el resultado de una continuación


La mejor manera de obtener el resultado es mediante una continuación, si está interesado en
Resultado de una tarea <T> , generalmente es porque desea hacer algo con el resultado como
tan pronto como la tarea original se haya completado (figura 5.17).
Cuando utiliza ContinueWith , la tarea de continuación no se inicia hasta el anterior.
la tarea ha finalizado, y la Acción <Tarea <T>> que pasa se llama utilizando el comando now-
tarea terminada como su parámetro. En este punto, puede acceder al Resultado .
En nuestra aplicación de correo electrónico hipotético podríamos usar esto para el inicio de sesión del usuario, una vez que la tarea
que inicia la sesión del usuario en su proveedor de correo electrónico, a menudo devolverá algún tipo de
token de autorización que puede pasarse a una continuación para usarse para cargar correos electrónicos para
ese usuario

Page 162
132 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

1. Una continuación es 2. La primera tarea termina y el


creado en la tarea. continuación se ejecuta con el
primera tarea como su parámetro.

UI Crear Crear
hilo tarea siguiente tarea

Tarea Calendario Calendario


planificador tarea siguiente tarea

Antecedentes Encargarse de
Ejecutar tarea
hilo resultado

Hora

Figura 5.17 Las continuaciones son una buena forma de manejar el resultado de una tarea porque se ejecutan
una vez completada la tarea y tener acceso al resultado de la tarea original.

5.5.4 Excepciones de tareas


Cuando un barista hace café, naturalmente pensamos en el camino feliz: tienen la tarea

https://translate.googleusercontent.com/translate_f 103/131
23/2/2020 Jim Bennett
con hacer nuestro café, y lo obtenemos una vez que está hecho. También está el camino triste: el
la cafetera está rota, no hay más granos, o el barista ha tenido suficiente
y renuncia en el acto. Estos caminos tristes conducen al resultado de la falta de café y una disculpa
del servidor
Lo mismo podría suceder en nuestra aplicación de correo electrónico: podría ir al proveedor de correo electrónico a
recibir correo electrónico, pero si el dispositivo no tiene conexión, el resultado no sería una lista de nuevos
correos electrónicos; en cambio, sería un mensaje de pérdida de conexión.
Estos caminos tristes son excepciones. Intentamos ejecutar una tarea, hacer café o descargar
correo electrónico, y algo sale mal, por lo que nuestra tarea no se completa como se esperaba. Nosotros no
tener un resultado, y tenemos una razón para el fracaso. Lo mismo sucede con las tareas de C #:
Si no tienen éxito debido a una excepción, no tenemos un resultado. En cambio tenemos un
fallado tarea también se refirió a como en fallo tarea.
Cuando una tarea se completa debido a una excepción, la propiedad IsCompleted se establece en
cierto , y también lo es la propiedad IsFaulted . Además, la propiedad Excepción se establece en
una AggregateException , envolviendo la excepción lanzada dentro de la tarea. Si no
hacer cualquier cosa con esta excepción, se volverá a lanzar en el subproceso finalizador (un subproceso
utilizado por el recolector de basura), lo que hace que su aplicación finalice. Hay un par de
cosas que puede hacer para evitar que esto suceda:
▪ Llame al método Wait en la tarea, y esta llamada al método volverá a arrojar la excepción.
para que pueda manejarlo adecuadamente.

Page 163
Actualizando la IU 133

▪ Acceda a la propiedad Excepción , incluso si no hace nada con ella, solo lea el
El valor evitará que la excepción se vuelva a generar en el subproceso finalizador.

Lo correcto es atrapar estas excepciones y manejarlas con gracia, pero


surgen problemas si usa una continuación. ¿Cómo puedes decir a continuación que algunos-
¿La cosa ha fallado? Puede detectar la excepción e informar la falla a través del Resultado ,
usando un valor que tiene un significado explícito de falla, pero este no siempre es el mejor o
la manera más fácil.
En cambio, la mejor manera es no atrapar la excepción en absoluto. Una tarea se completa una vez
el código está terminado, ya sea porque todo se ha ejecutado correctamente o porque hay
fue una excepción no manejada. De cualquier manera, IsCompleted será verdadero porque el código
ha completado. Sin embargo, en el caso de una excepción, el resultado será el predeterminado
valor para el tipo (por ejemplo, nulo para clases, 0 para números), la propiedad IsFaulted
erty se establecerá en true y la propiedad Exception se establecerá en AggregateExcep-
ción que envuelve la excepción que se lanzó. Si el código terminó sin un
excepción, IsFaulted será falso y la propiedad Exception será nula . Podemos
use estos valores en nuestra continuación para ver cómo terminó la tarea y actúe en consecuencia.
La siguiente lista muestra algunos pseudocódigos para esto.

Listado 5.6 Comprobando si una tarea falló con una excepción no controlada

público vacío DoSomething ()


{ Comprueba si la tarea
Task.Run (() => DoSomethingThatCanThrow ()) terminó debido a una excepción
.ContinueWith (t =>
{ Si la tarea terminó debido
si (t.Faulted) a excepción, informes
ShowException (t.Exception); La excepción
más
... Si no hubiera un
}); excepción, continúa
} con la continuación

Su código siempre debe verificar si la tarea falló, y si lo hizo, debe


Siempre acceda a la propiedad Excepción al menos una vez. Si hace esto, puede asegurarse de que
la excepción no se vuelve a lanzar cuando se finaliza la tarea, matando su aplicación.

5.6 Actualizando la IU
En nuestra cafetería, el servidor es el único punto de interacción. El cliente da
su orden al servidor, el servidor hace que los baristas hagan el café, y el servidor
llama al cliente una vez que el café está listo y se lo entrega (figura 5.18). Esto es
bueno desde la perspectiva del cliente: pueden salir y hacer lo que quieran, y
Una vez que sus cafés están listos, una persona los llama y recogen sus cafés. Si
cada vez que un barista terminaba de hacer un café solo llamaba al cliente, un cliente
Tomer que ordenó varios cafés iría de ida y vuelta entre lecturas
Las noticias y la recolección de café.

Page 164
134 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

https://translate.googleusercontent.com/translate_f 104/131
23/2/2020 Jim Bennett

Orden Recoger
café café

Tomar Obtener
orden café

Figura 5.18 Solo un servidor


Hacer café interactúa con los clientes: ellos entregan
fuera de las tareas a los baristas que hacen café
y luego retomar el control a mano
El café al cliente.
Hora

En nuestra cafetería, el servidor es el único punto de contacto con el cliente. Lo mismo


es cierto para la interfaz de usuario: solo el hilo de la interfaz de usuario puede actualizar la interfaz de usuario. Es el único hilo que puede
actualizar controles, cambiar diseños o cargar nuevas pantallas. Esto se hace cumplir; si intentas
Actualice la interfaz de usuario desde un subproceso en segundo plano utilizando una tarea, obtendrá una excepción. por
ejemplo, si se ejecuta una tarea para descargar todos los correos electrónicos nuevos en una aplicación de correo electrónico, la IU de la aplicación
deben actualizarse una vez que se realiza la tarea para mostrar estos nuevos correos electrónicos. El código para
actualizar la interfaz de usuario deberá estar en el hilo de la interfaz de usuario, si está dentro de la tarea de descarga, y
por lo tanto, ejecutándose en un subproceso en segundo plano, bloqueará la interfaz de usuario.
Veamos esto en acción. Subiremos una capa desde el modelo de vista a la vista y
obtenga un ejemplo de código simple para mostrar esto actualizando la IU de iOS desde una tarea.
Revierta todos los cambios que ha realizado en FirstViewModel en este capítulo y luego en
FirstView (dentro de FirstView.cs en la carpeta Vistas de HelloCrossPlatform-
World.iOS project) realice el cambio que se muestra en la siguiente lista.

Listado 5.7 La actualización de la interfaz de usuario desde un subproceso en segundo plano dará una excepción

usando System.Threading.Tasks; Agregue esta nueva directiva de uso


... al inicio del archivo.
anulación pública void ViewDidLoad ()
{
Al final de ViewDidLoad existente
...
método, agregue este código para crear una nueva tarea,
Task.Run (() => DoSomething ());
y ejecutarlo en un hilo de fondo
}
llamando al nuevo método DoSomething.
anular DoSomething () El nuevo método que es
{ correr en la tarea
Task.Delay (TimeSpan.FromSeconds (5)). Wait ();
TextField.Text = "Foo";
Después de un retraso, la interfaz de usuario se actualiza
} estableciendo la propiedad Text en
El campo de texto.

Page 165
Actualizando la IU 135

Parece que este código hace algo en segundo plano y luego actualiza la IU a
muestra "Foo". Pero si ejecuta la aplicación iOS, no hará lo que podría esperar.
Si está utilizando Xcode 8 con el SDK de iOS 10, obtendrá una buena excepción, que se muestra en
figura 5.19.

Figura 5.19 La actualización de la interfaz de usuario de iOS desde un subproceso en segundo plano proporciona un acceso de subproceso
excepción.

Esta excepción nos dice que estamos en el hilo equivocado. Estamos llamando a un método UIKit
que solo se puede invocar desde el hilo de la interfaz de usuario ( UIKit es el nombre que Apple le da al
clases que usa para las IU).
Si está utilizando Xcode 9, entonces, en lugar de una excepción, no sucederá nada.
Xcode 9 ha movido las comprobaciones de las excepciones en el código a un Comprobador de subprocesos principal,
que es tanto una aplicación independiente como una herramienta integrada en el depurador Xcode.
Al momento de escribir, esta herramienta no se ha integrado en el depurador Xamarin.
La ventaja de este cambio es que su aplicación no se bloqueará si un control de IU se actualiza
el hilo de la interfaz de usuario. La desventaja es que las actualizaciones de la interfaz de usuario pueden perderse.
¿Cómo podemos actualizar la interfaz de usuario del código que se ejecuta en un subproceso en segundo plano?

5.6.1 El planificador de tareas de la interfaz de usuario


En nuestra cafetería tenemos dos tipos de personas que pueden trabajar. Tenemos un servidor
quien se ocupa de la interacción con el cliente, y baristas y lavaplatos que trabajan detrás
las escenas para hacer café, té o lavar tazas. Estos dos grupos son muy distintos.

https://translate.googleusercontent.com/translate_f 105/131
23/2/2020 Jim Bennett
y tienen roles y limitaciones muy específicos. Solo tiene un servidor como punto único
de contacto para el cliente, pero el personal detrás de escena puede escalar en función de
demanda: necesitaría más baristas durante la fiebre del café de la mañana que al final
del día.
Puedes pensar en hilos de manera similar. Cuando se crea un hilo, vive dentro de un
contexto de sincronización . Un contexto de sincronización es un grupo de uno o más hilos
que comparten las mismas características, por lo que si algún código puede ejecutarse en un hilo dentro de ese
contexto, puede ejecutarse en cualquier hilo. Esto es igual que el personal de nuestra cafetería: todos los baristas
tienen las mismas características y pueden hacer café, pero solo el servidor puede interactuar
Con el cliente. Cuando el programador de tareas ejecuta una tarea, lo hace utilizando un
contexto de sincronización general, al igual que las tareas en nuestra cafetería se asignan a personas específicas
ple. Los baristas recogen tareas para hacer café, los lavaplatos recogen tareas para obtener más tazas,
y el servidor recoge tareas para dar el café terminado a los clientes.
Por defecto, una tarea será programada por el programador de tareas predeterminado, que
utilizar subprocesos del contexto de sincronización predeterminado (también denominado conjunto de subprocesos

Page 166
136 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

contexto de sincronización ), lo que significa que ejecuta las tareas utilizando uno de los muchos grupos
hilos de fondo disponibles. Estos hilos de fondo son creados por usted
programador de tareas, por lo que no hay nada que deba hacer en su código para usarlos. Estas
los subprocesos comparten las mismas características: todos se ejecutan en segundo plano y son
todo se detuvo cuando se detiene el subproceso de la interfaz de usuario. Este es el tipo predeterminado de hilo utilizado cuando
crea una tarea usando Task.Run o construye una nueva instancia de Task o Task <T> .
Hay otro contexto de sincronización que nos interesa: el hilo de la interfaz de usuario
contexto de sincronización. Este contexto contiene solo un hilo, el hilo UI. diferente a
el contexto de sincronización predeterminado, que utiliza el planificador de tareas predeterminado, el
El contexto de sincronización de subprocesos de la IU no está fácilmente disponible desde una propiedad estática. En lugar
tenemos que utilizar un método estático en la TaskScheduler clase, FromCurrentSynchroni-
zationContext () . Esto siempre devolverá el contexto de sincronización para el actual
hilo que se llama. Si llama a esto desde una tarea que se ejecuta en segundo plano,
recuperar el planificador predeterminado, pero si lo llama desde el hilo de la interfaz de usuario, obtendrá un
programador de tareas que puede usar para ejecutar sus tareas en el hilo de la interfaz de usuario (figura 5.20).

1. Se crea una continuación en el 2. La tarea termina y el


tarea para actualizar el texto usando el continuación se ejecuta de nuevo
Programador de tareas de subprocesos UI. en el hilo de la interfaz de usuario.

UI Crear Encargarse de
hilo tarea resultado

Tarea Calendario
planificador tarea

Antecedentes
Ejecutar tarea
hilo

Hora

Figura 5.20 Las continuaciones se pueden ejecutar en cualquier programador de tareas, por lo que se pueden configurar para que se ejecuten nuevamente en el
UI hilo.

Este programador de tareas colocará su código en la cola de mensajes que el subproceso de interfaz de usuario proporciona
cesses. Su código se ubicará en esta cola detrás de cualquier otro mensaje que sea el hilo de la interfaz de usuario
ya procesando, como eventos de IU. Una vez que los mensajes en frente han sido pro
cesado (si lo hay), se ejecutará su código.

MARCANDO SU CÓDIGO EN EL HILO UI A menudo escuchará el término mar-


shaling cuando se habla de código multiproceso. Marshaling esencialmente significa
ejecutar código en un subproceso diferente, por ejemplo, cuando ejecuta una tarea
usando el programador de tareas de la interfaz de usuario, está ordenando su código en el hilo de la interfaz de usuario.

Page 167
Actualizando la IU 137

El patrón habitual aquí es crear una tarea en el hilo de la interfaz de usuario que haga algo de trabajo en el
fondo, y use una continuación de tarea para ejecutar un poco más de código en la interfaz de usuario
hilo diciendo a la continuación qué planificador de tareas utilizar. La siguiente lista
muestra cómo hacer esto.

El listado 5.8 que usa el programador de tareas de la interfaz de usuario permite que la interfaz de usuario se actualice desde una tarea

https://translate.googleusercontent.com/translate_f 106/131
23/2/2020 Jim Bennett
anulación pública void ViewDidLoad () Al llamar a ContinueWith, usted
{ puede pasar un programador de tareas que
... puedes usar para ejecutar la tarea.
planificador var =
TaskScheduler.FromCurrentSynchronizationContext ();
Task.Run (() => DoSomethingLong ())
.ContinueWith (t => TextField.Text = "Foo", planificador);
}

nulo DoSomethingLong ()
La actualización de la interfaz de usuario ha sido eliminada
{
del método DoSomething como
Task.Delay (TimeSpan.FromSeconds (5)). Wait ();
ahora está en la continuación.
}

Si realiza este cambio, compila y ejecuta esto, una vez más todo funcionará. Vamos
divide esto en pasos:
1 El subproceso de la interfaz de usuario solicita el planificador de tareas para el actual control de sincronización
texto, que será el programador de tareas para el subproceso de la interfaz de usuario.
2 El subproceso de la interfaz de usuario crea y ejecuta una tarea.
3 El subproceso de la interfaz de usuario configura una continuación de la tarea, dándole una acción para ejecutar y pasar
en el programador de tareas de subprocesos de la interfaz de usuario. FromCurrentSynchronizationContext es evalu-
antes de que se configure la tarea, por lo que se invocaría en el subproceso de interfaz de usuario y el
el valor resultante se pasaría a la llamada a ContinueWith , que configura el
continuación.
44 El programador de tareas predeterminado ejecuta la primera acción en un subproceso en segundo plano.
55 Cuando se completa esta acción, el planificador de tareas de la IU ejecuta la continuación
acción.

5.6.2 Usando el poder de MVVM


Si tiene un modelo de vista con un comando que está vinculado a un control de IU, como un pero-
ton, cuando el usuario hace clic en el botón, el código dentro del comando se ejecuta en la interfaz de usuario
hilo. Al usar continuaciones que usan el programador de tareas de la interfaz de usuario, puede escribir código
dentro de su comando que se ejecuta en un hilo de fondo y luego vuelve a
el hilo de llamada para realizar cualquier acción que hará que la interfaz de usuario se actualice.
Sin embargo, dependiendo del marco MVVM que esté utilizando, es posible que no necesite
preocúpese demasiado por ordenar su código nuevamente en el hilo de la interfaz de usuario.
Una forma de hacer que la interfaz de usuario se actualice es mediante notificación de cambio de propiedad.
opciones: vincula un control de IU a una propiedad en el modelo de vista, actualiza la propiedad,

Page 168
138 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

genera una notificación de cambio de propiedad y la IU se actualizará. Esta actualización de la interfaz de usuario tiene que
hacerse en el hilo de la interfaz de usuario.
Afortunadamente, todos los buenos frameworks MVVM se encargan de esto. En la capa de unión, el
se detecta un evento de cambio de propiedad, se lee el valor a establecer y la capa de enlace
ejecutar la actualización de la interfaz de usuario en el hilo de la interfaz de usuario, independientemente de qué hilo se use para elevar
notificación de cambio de propiedad (figura 5.21). Puede ver esto cambiando su código a
actualice la propiedad en el modelo de vista en lugar de actualizar la IU directamente. Si lo haces
esto desde un hilo de fondo, puede ver la actualización de la interfaz de usuario sin excepción
arrojado La siguiente lista muestra este cambio.

UI Crear Actualizar
hilo tarea tarea

La capa de unión
mariscal automático
Tarea Calendario la actualización de la interfaz de usuario en
planificador tarea el hilo de la interfaz de usuario.

Aumento
Antecedentes
Ejecutar tarea propiedad cambiada
hilo
notificación

Hora

Figura 5.21 Cuando se detecta un evento de cambio de propiedad, la capa de enlace ordenará la llamada a
actualizar la interfaz de usuario en el hilo de la interfaz de usuario automáticamente.

Listado 5.9 Enlazar automáticamente los cambios de propiedad de Marshals en el hilo de la interfaz de usuario

anulación pública void ViewDidLoad ()


{
...
var vm = (FirstViewModel) ViewModel;
Task.Run (() => DoSomethingLong ())
.ContinueWith (t => vm.Name = "Foo");
La continuación ya no es
}
ejecutar usando el programador de tareas de la interfaz de usuario.
Del hilo de fondo,
Cada vista derivada de una vista base MvvmCross
la propiedad Nombre en la vista
(como MvxViewController o MvxActivity) tiene un
se puede configurar el modelo, y el
Propiedad ViewModel que obtiene el modelo de vista para
asas de enlace que actualizan la IU

https://translate.googleusercontent.com/translate_f 107/131
23/2/2020 Jim Bennett
esta vista. Es del tipo IMvxViewModel, por lo que necesita en el hilo derecho.
ser enviado al tipo de su modelo de vista.

Si realiza este cambio y ejecuta la aplicación, verá la actualización de la interfaz de usuario. éste es uno de
poderes de un buen marco como MvvmCross: abstrayendo lo difícil, dejando
centrarse en lo que debe hacer su código en lugar de las complejidades de cómo debería
ser hecho

Page 169
Asíncrono y espera 139

EVITE EL CAST TO FIRSTVIEWMODEL UTILIZANDO GENÉRICOS La base MvvmCross


las vistas también están disponibles en una forma genérica que toma un argumento de tipo para
Tipo de modelo de vista. Si los usa, la propiedad ViewModel será del
escriba correctamente y no necesitará la conversión a FirstViewModel . Para ver esto en
acción, cambie el tipo base de la vista de iOS a MvxViewController <Primero-
ViewModel> . Luego puede cambiar la continuación para que continúe con (t =>
ViewModel.Name = "Foo"); .

Está bastante claro que las tareas son realmente bastante útiles. Te permiten empaquetar algunos
código y dispararlo para que se ejecute en otro hilo. Entonces puedes crear otra tarea para
volver a ejecutarse en el hilo de llamada una vez que se complete el primero. Esto es bastante popu-
patrón lar con la interfaz de usuario de aplicaciones de gestión de código x en el fondo, y luego ejecutar código y vuelta
en el hilo de la interfaz de usuario. No es perfecto, y la forma en que maneja los valores de retorno y la excepción
ya sea esperando a que se complete la tarea o usando una continuación, puede reducirse-
derecho torpe.
La buena noticia para nosotros los desarrolladores de C # es que, como parte de C # 5, Microsoft ha agregado
nuevas características interesantes para que esto sea mucho más fácil: asíncrono y aguarde .

5.7 Asíncrono y espera


En C # 5.0 se agregaron dos nuevas palabras clave, asíncrona y aguardando . Estos no hacen nada en
términos de código; en cambio, son sugerencias del compilador, que le dicen al compilador que maneje el código
marcado con estas palabras clave de manera diferente. Async es la abreviatura de asíncrono: código que puede
ejecuta varias cosas al mismo tiempo. A menudo oirá hablar de código multiproceso
referido como código asincrónico .

5.7.1 Las palabras clave async y aguardan


El objetivo de las palabras clave asíncronas y en espera es permitirle tomar el patrón de "ejecutar
código x en segundo plano, luego ejecute el código y de nuevo en el proceso de sincronización actual
texto "y simplificarlo. Marca un método como asíncrono y cuando llama a otro asíncrono
métodos de este método, marca las llamadas para ejecutarlas con wait . La espera
le dice al compilador que en algún lugar del método al que está llamando, algún trabajo
se realice en un subproceso en segundo plano utilizando una tarea, y para retrasar la ejecución del resto del
método de llamada hasta que el método esperado haya terminado lo que está haciendo. En la media
tiempo, el hilo actual puede procesar otro código, y una vez que el método esperado com
pletes, el resto del método de llamada finaliza.

ESPERAR NO CREA UN HILO DE FONDO PARA USTEDES Hay un común


idea errónea sobre async y esperar que realmente ejecuten su código
en el fondo. Este no es el caso. Antes de comenzar a profundizar en esto en
Más detalles, es importante tener en cuenta esto.

Comencemos con un ejemplo de código simple en la capa de vista dentro de nuestra aplicación iOS. Haremos
la aplicación espera y luego actualiza la interfaz de usuario. Comience cambiando la clase FirstView , en First-
View.cs en el proyecto HelloCrossPlatformWorld.iOS, al revertir el anterior
cambios realizados en este capítulo y haciendo los cambios que se muestran en la siguiente lista.

170 de 1189.
140 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

Listado 5.10 La ejecución de tareas en segundo plano no afecta cuando se ejecuta el resto del código

anulación pública void ViewDidLoad () El código de enlace existente


{
... Se llama a Task.Delay para ejecutar un
Task.Delay (TimeSpan.FromSeconds (5)); tarea de fondo para esperar 5 segundos.
TextField.Text = "Foo";
} El campo de texto en la IU se actualiza.

Lea el flujo de este método. El sistema operativo llama a varios métodos de ciclo de vida
cuando se muestran las pantallas: los métodos a los que se llama cuando aparece una pantalla,
peras, o va a otros estados. Uno de estos métodos de ciclo de vida en iOS es ViewDidLoad ,
que el sistema operativo llama tan pronto como la vista se ha cargado completamente y se muestra en la pantalla.
Esta llamada se ejecuta en el subproceso de interfaz de usuario como ya ha visto, y configura los enlaces en

https://translate.googleusercontent.com/translate_f 108/131
23/2/2020 Jim Bennett
el código existente que no hemos cambiado, inicia una tarea que espera 5 segundos en el
fondo y luego actualiza la IU (figura 5.22). Si ejecuta este código, verá
lo que espera: la interfaz de usuario muestra "Foo" en el campo de texto inmediatamente porque la espera
sucede en una tarea, en otro hilo.

ViewDidLoad

UI comienzo Crear Actualizar Salida


hilo método tarea texto método

Antecedentes
Demora por 5 segundos
hilo

Hora

Figura 5.22 Línea de tiempo del método ViewDidLoad : comienza el método de retraso, el
la tarea de retraso se crea y se inicia en un subproceso en segundo plano, la IU se actualiza y
El método termina.

Sería mejor si la interfaz de usuario se actualizara después de la espera de 5 segundos, pero sin la interfaz de usuario
encerrado por esos 5 segundos. Hagamos un par de pequeños cambios a este método para
lograr esto en el siguiente listado.

Listado 5.11 Agregando async y aguardando a nuestro método

anulación pública asíncrona void ViewDidLoad () El método está marcado.


{ con la palabra clave asincrónica.
...
esperar Task.Delay (TimeSpan.FromSeconds (5)); La llamada a Task.Delay es
TextField.Text = "Foo"; prefijado por esperar.
}

Página 171
Asíncrono y espera 141

Realice estos cambios de código y vuelva a ejecutar el código. La aplicación se iniciará, espera 5 segundos
y luego actualice el campo de texto. Durante los 5 segundos antes de que el campo de texto sea
actualizado, intente interactuar con la aplicación para ver si la aplicación responde. Notarás que
es. A diferencia de llamar a Wait on your task, que bloquea el hilo durante los 5 segundos, esto
no bloquea La llamada a ViewDidLoad por el sistema operativo regresa tan pronto como la llamada a Delay
se realiza y el resto de la llamada al método se vuelve a llamar en el subproceso original (UI)
más tarde (figura 5.23).

ViewDidLoad Continuación

UI comienzo Crear Salida Actualizar


hilo método tarea método texto

Antecedentes
Demora por 5 segundos
hilo

Hora

Figura 5.23 Si espera la tarea de retraso, el método ViewDidLoad finaliza tan pronto como
se llama a la espera , y el resto del método se llama en una continuación
en el hilo original

El principio básico aquí es que puede marcar un método como asíncrono para decirle al compilador que
estás planeando usar await en tu método. Luego llamas aguardar en una tarea (ya sea
uno que cree o uno que sea devuelto por un método) y el compilador, detrás de
escenas, tomarán el resto del código en el método y lo pondrán en una continuación usando
el contexto de sincronización original como el hilo para ejecutar la continuación.

DESPUÉS AWAIT, el código se ejecuta en el mismo SINCRONIZACIÓN CONTEXTO El


el código antes y después de una espera se ejecutará en el mismo contexto de sincronización,
pero no necesariamente el mismo hilo. El contexto de sincronización de la interfaz de usuario tiene un
subproceso único, por lo que si espera un método del subproceso de interfaz de usuario, el código que
viene después de que se ejecute en el hilo de la interfaz de usuario; si esperas de un fondo
subproceso, el código después de la espera puede ejecutarse en un subproceso de fondo diferente.

Puede pensar en el comportamiento del código en el listado 5.11 como análogo al código en
El siguiente listado.

El Listado 5.12 await usa el contexto de sincronización del hilo original

anulación pública void ViewDidLoad ()


{
...
Task.Delay (TimeSpan.FromSeconds (5))
.ContinueWith (t => TextField.Text = "Foo",

https://translate.googleusercontent.com/translate_f 109/131
23/2/2020 Jim Bennett
TaskScheduler.FromCurrentSynchronizationContext ());
}

Page 172
142 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

¿Cuál es la gran ventaja de async y esperar ? Primero, hace que su código sea mucho más fácil de
leer. Imagínese si en lugar de tener una llamada para Continuar con cinco. Eso podría
ser más difícil de leer que simplemente usar esperar . Segundo, y probablemente lo más importante, usted
puede usar valores de retorno y excepciones como si no hubiera continuaciones involucradas.
Pensando nuevamente en nuestro ejemplo de aplicación de correo electrónico, cuando el usuario inicia la aplicación, necesita
llamar a un servicio web para autenticar al usuario y luego recuperar una autenticación
simbólico. Una vez autenticado, debe llamar a otro servicio web y pasar el
token de catión, para descargar una lista de correos electrónicos nuevos, y luego necesita descargar el mensaje completo
contenido de cada nuevo correo electrónico, pasando nuevamente el token de autenticación. En cada etapa
querrá actualizar la interfaz de usuario: una vez que haya iniciado sesión, mostrará los correos electrónicos, cuando haya
descargó la lista de correos electrónicos nuevos, mostrará un resumen, y como cada correo electrónico está completamente
descargado la interfaz de usuario se actualizará para mostrar los detalles de cada correo electrónico. Si en cualquier momento
estas acciones debían fallar con una excepción (como si no hubiera conectividad de red
ity, una ocurrencia común con las aplicaciones móviles), el código debería detener la descarga
ing correos electrónicos y manejar la excepción, tal vez mostrando un mensaje al usuario. los
La siguiente lista contiene algunos pseudocódigos para esto, usando continuaciones.

Listado 5.13 Pseudocódigo para descargar correos electrónicos y actualizar la IU

public void HandleLogInAndDownloadEmails ()


{ Inicia una tarea para iniciar sesión
token de cadena = nulo;
Task.Run (() => LogIn ())
Crea una continuación
de vuelta en el hilo de la interfaz de usuario
.ContinueWith (t1 =>
{
if (t1.IsFaulted)
Si la tarea original arrojó
ShowException (t1.Exception);
una excepción, lo muestra
más
{
UpdateUIAfterLogIn ();
Si el original
Task.Run (() => DownloadEmailList (token))
la tarea no arrojó Comienza una continuación
.ContinueWith (t2 =>
una excepción, para descargar el
{ correos electrónicos, etc.
actualiza la interfaz de usuario
if (t2.IsFaulted) y así
ShowException (t2.Exception);
más
{
UpdateUIWithNewEmails ();
foreach (var email en t2.Resultado)
{
Task.Run (() => DownloadEmail (token, correo electrónico))
.ContinueWith (t3 =>
{
if (t3.IsFaulted)
ShowException (t3.Exception);
más
UpdateUIWithDownloadedEmails ();
}, TaskScheduler.FromCurrentSynchronizationContext ());
}
}

Page 173
Asíncrono y espera 143

}, TaskScheduler.FromCurrentSynchronizationContext ());
}
}, TaskScheduler.FromCurrentSynchronizationContext ());
}

Este es un código muy complicado, en parte porque estamos cambiando hilos con tanta frecuencia y
en parte porque necesitamos seguir consultando la Tarea pasada a la continuación de
cualquier excepción y por el valor de retorno.
No solo pueden sincronizar y esperar eliminar la necesidad de continuar, sino que también
ayuda con valores de retorno y excepciones. Como ya sabe, puede llamar en espera en un
Tarea , pero lo poderoso de esperar es que puede devolver el resultado de una Tarea <T> . Si
que esperan una tarea , no hay valor de retorno, por lo que la aguardan no devuelve nada, pero si
que esperan una tarea <T> , el valor de retorno de la llamada es una instancia de T , el que está vuelto
por la tarea Si su tarea arroja una excepción, normalmente se traga y solo se hace
disponible a través de la propiedad Excepción en la Tarea pasada a la continuación. Pero
Si usa async y espera , la excepción se produce como si no estuviera en una tarea.
Reescribamos el listado 5.13 para hacer esto, como sigue.

Listado 5.14 Usando async y aguardando para limpiar nuestro código

Tarea pública asíncrona HandleLogInAndDownloadEmails ()


El método ahora devuelve
{
Tarea y está decorado con

https://translate.googleusercontent.com/translate_f 110/131
23/2/2020 Jim Bennett
tratar La palabra clave asíncrona.
{
token var = espera Task.Run (() => LogIn ());
El token es
UpdateUIAfterLogIn ();
regresado
correos electrónicos var = esperar Task.Run (() => DownloadEmailList (token));
de la tarea
UpdateUIWithNewEmails (); La interfaz de usuario puede ser
Gracias a
foreach (var correo electrónico en correos electrónicos) actualizado porque
Esperar llamada.
{ estamos de vuelta en el
esperar Task.Run (() => DownloadEmail (token, correo electrónico)); hilo de llamada (el
UpdateUIWithDownloadedEmails (); Subproceso de interfaz de usuario) después
} En espera de la tarea.
} Podemos continuar
captura (Excepción ex) este patrón para el
Todo el método puede ser envuelto resto del método
{
en un intento / captura porque espera toma
ShowException (ex); cuidado de lanzar cualquier excepción.
}
}

El código en el listado anterior hace lo mismo que el código en el listado 5.13, pero es
Más limpio y más fácil de leer. También parece tener un tipo de tarea de retorno , pero no
Parece devolver cualquier cosa. Veamos por qué esto es mirando cómo escribimos asíncrono
métodos.

5.7.2 Escribir sus propios métodos asíncronos


En los listados que acabamos de ver, los métodos se marcaron con la palabra clave asíncrona ,
que le dice al compilador que el método contendrá llamadas para esperar tareas. Si no

Page 174
144 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

tiene esta palabra clave en su método, no puede esperar . Puede probar esto rápidamente eliminando
ing la palabra clave asincrónica del método ViewDidLoad que cambió anteriormente. Llevarlo a cabo
y tu aplicación no se compilará.
M Arking MÉTODOS AS ASYNC
No puede marcar cualquier método como asíncrono; solo puede usarlo en métodos que tengan
devuelve el tipo de vacío , Tarea o Tarea <T> , y no puede usarlo en métodos sin param-
Eters o parámetros de referencia. La palabra clave asíncrona no es parte de la firma del método, por lo que
no puede usarlo en interfaces, pero puede agregarlo cuando está anulando métodos: ha
Ya lo vi cuando lo agregó a la anulación de ViewDidLoad en la aplicación iOS.
Cuando tiene un método asíncrono , la intención habitual es que la persona que llama lo espere y
Para que esto suceda, el método debe tener un tipo de retorno de Tarea o Tarea <T>: recuerde,
solo puede llamar a esperar en una tarea, por lo que si su método es nulo, no hay nada
esperar
Cuando marca el método como asíncrono , en realidad no devuelve una instancia de Tarea
o Tarea <T> ; simplemente no devuelve nada o una instancia de T , y el compilador hace el resto
para usted, envolviendo todo en una tarea para que se pueda esperar el método. Viste esto
en el listado 5.14: el método HandleLogInAndDownloadEmails se marcó como return-
ing Tarea pero no tenía un valor de retorno explícito.
Puede marcar un método que devuelva vacío como asíncrono , pero este método no puede ser
esperado ya que no hay tarea que esperar. Esto normalmente no es un problema porque no hay
valor de retorno para preocuparse, pero tenga en cuenta que si llama a un método vacío asíncrono ,
es posible que no se complete antes de que se ejecute el resto del código porque se ejecutarán algunas partes
en el fondo. Idealmente, nunca debe marcar un método vacío como asíncrono a menos que
no tiene otra opción, como con controladores de eventos o anular métodos existentes.
Si anula un método de anulación y hace que la anulación sea asíncrona , debe tener en cuenta
que todo el código no estará terminado antes de que regrese el método. Por ejemplo, anulado
ing un método como viewDidLoad en el controlador de vista iOS y lo que es asíncrono voluntad
significa que el método volverá una vez que la primera tarea en segundo plano comience a ejecutarse. Si tu
tenía algún código para configurar la interfaz de usuario, como la creación de enlaces, y si este código llega
después de la tarea esperada, no se ejecutará hasta que se complete la tarea. Esto podría significar que
su usuario usará una aplicación con una IU incompleta hasta que la tarea en segundo plano comience
pletes Es una buena práctica esperar solo los métodos después de completar toda la configuración de la interfaz de usuario, o
para mostrar alguna forma de progreso al usuario para que sepa que algo está sucediendo
y que necesitan esperar.
Tomemos nuestro último ejemplo y en la siguiente lista escriba algunos métodos asíncronos
para hacer el código más limpio.

Listado 5.15 Usando async para hacer su código más limpio

Tarea asincrónica <cadena> Iniciar sesión () {}


Los métodos para
los datos de carga son
Tarea asíncrona <IEnumerable <Email>> DownloadEmailList (token de cadena) {} marcado como asíncrono.

Async Task DownloadEmail (token de cadena, correo electrónico de cadena) {}

175 de 1189.

https://translate.googleusercontent.com/translate_f 111/131
23/2/2020 Jim Bennett
Asíncrono y espera 145

Tarea pública asíncrona HandleLogInAndDownloadEmails ()


{
tratar
{ No hay más
token var = espera LogIn ();
llamadas a Task.Run.
UpdateUIAfterLogIn ();
correos electrónicos var = aguardar DownloadEmailList (token);
UpdateUIWithNewEmails ();
foreach (var correo electrónico en correos electrónicos)
{
aguarde DownloadEmail (token, correo electrónico);
UpdateUIWithDownloadedEmails ();
}
}
captura (Excepción ex)
{
ShowException (ex);
}
}

En este listado, el código es mucho más limpio, y ahora es responsabilidad de los métodos
que se llaman para crear las tareas que se ejecutan en segundo plano.
Recuerde, solo usar async y esperar no creará las tareas para usted, todavía está
responsable de esto, ya sea directamente creando la tarea o indirectamente esperando
Otro método que crea una tarea. Por ejemplo, en el caso de acceder a un servicio web,
hay un paquete NuGet disponible de Microsoft llamado HttpClient que hará esto
para ti, tiene algunos métodos asíncronos que puedes esperar que crearán la tarea y
ejecute la llamada web en segundo plano, por lo que todo lo que necesita hacer en su código es marcar su
métodos como asíncrono y aguardan todas las llamadas. Este es uno de los inconvenientes de async y
aguarde , debe marcar todo como tareas asíncronas y de retorno. Si su servicio web llama
está enterrado diez llamadas en la pila de llamadas, las diez llamadas deben esperarse y deben regresar
Tareas.

¿Qué pasa con la acción y la función? Al igual que los métodos, las lambdas se pueden marcar como
asíncrono , y puede esperar tareas. Esto significa que puede crear acciones asincrónicas y
funciones que usan las mismas palabras clave, sintaxis como var myAction = new
Acción (async () => wait MyMethod ()); o var myFunc = nuevo
Func <int> (async () => wait MyIntMethod ()); .

R eturning T PREGUNTA En lugar de utilizar ASYNC y esperar


Los métodos asíncronos tienen un tipo de retorno de Tarea o Tarea <T> , pero en realidad nunca regresa
la tarea tu mismo. En cambio, espera otros métodos que devuelven tareas y devuelven el
tipo relevante, y el compilador teje su magia sobre su código para administrar todo el
esperar declaraciones y en realidad devolver una tarea al final del método que puede ser
esperado por el código de llamada.

Page 176
146 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

Si solo tiene una llamada en su método que espera , y es la última (o solo)


lo que hace su método, entonces en lugar de marcar su método como asíncrono y esperar
la llamada, simplemente puede devolver la tarea. Vea los siguientes dos listados.

Listado 5.16 Uso de un método asíncrono cuando puede devolver una Tarea

Tarea pública asíncrona MakeCoffee ()


{
aguarde myCoffeeService.MakeCoffee ();
}

En este código, el método MakeCoffee es asíncrono , pero todo lo que hace es esperar una llamada a myCof-
feeService.MakeCoffee () . Para escribir menos código, puede soltar el modificador asíncrono y
simplemente devuelva el resultado de la llamada en lugar de esperarla.

Listado 5.17 Devolver una tarea en lugar de esperarla

Tarea pública MakeCoffee ()


{
devolver myCoffeeService.MakeCoffee ();
}

Este código es funcionalmente idéntico y, de hecho, es marginalmente más rápido. Usar esperar medios
el compilador tiene que generar código para rastrear los hilos en uso y asegurarse de que el código
después de que la espera ocurra en el hilo correcto. Y tiene que hacer esto para todos los asíncronos
métodos en la pila de llamadas actual. Si solo devuelve la tarea, este código adicional no es
necesario. Es una buena práctica devolver siempre una tarea si su método asíncrono solo espera
última llamada al método
C ONFIGURE A WAIT
Cuando espera una llamada a un método asíncrono , le está diciendo al compilador que desea

https://translate.googleusercontent.com/translate_f 112/131
23/2/2020 Jim Bennett
para garantizar que todo el código después de la espera se ejecute en el mismo contexto de sincronización que
El código antes de la espera . El compilador crea código para capturar la sincronización actual.
contexto de inicialización, llama a un método que está esperando y luego ejecuta el resto del actual
Método que utiliza el contexto de sincronización original. Hay un pequeño compilador sobre-
diríjase a esto: capturar el contexto de sincronización y volver a él.
Sin embargo, hay momentos en los que no le importa qué hilo el resto del
El código en su método actual se ejecuta. Por ejemplo, puede tener un método que
espera una llamada a la base de datos, luego realiza un procesamiento intensivo de CPU en los datos, return-
Resultados de un método de llamada que actualiza la interfaz de usuario. El procesamiento puede hacerse en
cualquier subproceso: es solo la actualización de la interfaz de usuario que debe suceder en el subproceso de la interfaz de usuario. los
La siguiente lista muestra algunos pseudocódigos que ilustran esto.

Listado 5.18 Realizar un cálculo largo en el hilo de la interfaz de usuario

Tarea pública asíncrona CalcAndUpdate ()


{ Desde el hilo de la interfaz de usuario,
resultado var = aguardar Calc ();
esperar una llamada a Calc

Page 177
Asíncrono y espera 147

myLabel.Text = resultado;
De vuelta en el hilo de la interfaz de usuario,
}
actualizar una etiqueta

Async público Task Calc ()


{ Desde el hilo de la interfaz de usuario, espera
datos var = esperar LoadData ();
una llamada a LoadData
return PerformLongCalculation (datos);
De vuelta en el hilo de la interfaz de usuario,
}
realizar un cálculo

En este código, la llamada al método LoadData cargará datos en un subproceso en segundo plano,
y luego Calc volverá al contexto de sincronización actual (el hilo de la interfaz de usuario)
para ejecutar el cálculo No nos importa qué hilo la llamada PerformLongCalculation
en realidad se ejecuta, solo que la actualización de la etiqueta ocurre en el hilo de la interfaz de usuario. Lo que podemos hacer
es hacer una llamada a un método para decirle al compilador que no queremos cambiar la sincronización
contextos de zation después de la espera , y el resto del método Calc puede ejecutarse en lo que sea
El hilo LoadData solía ejecutarse. Podemos hacer esto usando el método ConfigureAwait en
Tarea .

Listado 5.19 Uso de ConfigureAwait para evitar cambiar contextos

Async público Task Calc () De la interfaz de usuario


{ hilo, espera un
var data = await LoadData (). ConfigureAwait (false); llamar a LoadData
return PerformLongCalculation (datos);
En el mismo hilo utilizado por
}
LoadData, realiza un cálculo

Al llamar a ConfigureAwait (falso) , le estamos diciendo al compilador que permanezca en el mismo


hilo utilizado por la llamada que estamos esperando, pero solo por el resto de la actual
método, hasta que otro aguarde . Cuando volvamos a CalcAndUpdate , el código cambiará
volver al contexto de sincronización de llamadas. Pasar true a ConfigureAwait le dice al
compilador que desea volver al contexto de sincronización original
que es lo mismo que no llamarlo.
Al identificar cualquier método esperado en el código que nunca necesitará interactuar con
el subproceso de la interfaz de usuario y marcándolos con ConfigureAwait , puede hacer un pequeño rendimiento
Mejora de mance. Esto no solo ahorra tiempo de CPU al evitar almacenar el origen
contexto de sincronización final y volver a él más tarde, pero si su código constantemente
vuelve al subproceso de la interfaz de usuario para realizar un trabajo simple que podría ejecutarse en segundo plano
hilo, puede ralentizar su interfaz de usuario. Generalmente es una buena idea marcar todas las llamadas que espera
con ConfigureAwait en cualquier clase que no interactúe con la IU, como las clases en
La capa de tu modelo.

5.7.3 Comandos asincrónicos


Hemos analizado la construcción de métodos asíncronos breves y concisos que esperarán en otros asíncronos
métodos, que a su vez esperarán en llamadas a algo como HttpClient , que
crear tareas para acceder a un servicio web en un hilo de fondo. Este es un buen patrón, pero
¿Cómo llamamos a nuestro nuevo método asíncrono en primer lugar? Como ya has visto, nosotros

Page 178
148 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

puede anular un método nulo en nuestra vista, marcarlo como asíncrono y esperar nuestro nuevo
método allí. También podríamos conectar un evento a un botón de inicio de sesión, marcar el evento han-
dler como asíncrono (recuerde, los manejadores de eventos son siempre métodos nulos), y aguarde nuestro
método. Ninguno de estos es realmente MVVM, por lo que podríamos saltar al
ver la capa del modelo y llamar al método dentro de un comando que podemos vincular a nuestra vista,

https://translate.googleusercontent.com/translate_f 113/131
23/2/2020 Jim Bennett
ya sea con un clic de botón u otro evento, como una carga de pantalla. Porque nuestro método
es asíncrono , necesitamos un nuevo tipo de comando: un comando asíncrono.
Como ya ha visto, los comandos en el modelo de vista comienzan en el hilo de la interfaz de usuario, por lo que
para ejecutar código en segundo plano, necesita crear tareas. Por suerte para nosotros, todo lo bueno
Los marcos MVVM tienen implementaciones asincrónicas de ICommand que podemos usar.
En el caso de MvvmCross, hay MvxAsyncCommand . A diferencia de MvxCommand , que toma
una Acción como parámetro, MvxAsyncCommand toma una Func <Task>, una llamada que devuelve
como una tarea que se puede esperar.
Veamos esto en acción. Primero, revierta todos los cambios que ha realizado en FirstView en
la aplicación iOS en este capítulo, y realice los cambios que se muestran en la siguiente lista para
FirstViewModel .

Listado 5.20 Crear un comando asíncrono

El comando que estás creando es ahora


El método SayHello es
un MvxAsyncCommand, y se necesita un
marcado como asíncrono y
Func <Task>. Puedes pasarlo
devuelve una tarea. Recuerda,
método que devuelve una tarea.
no regresas explícitamente
FirstViewModel público (ITextToSpeech textToSpeech) una instancia de Tarea: la
{
el compilador lo maneja por usted.
this.textToSpeech = textToSpeech;
SayHelloCommand = new MvxAsyncCommand (() => SayHello ());
}

Tarea asincrónica SayHello ()


{
esperar Task.Delay (TimeSpan.FromSeconds (5)); Llamadas en espera en la tarea.
textToSpeech.Speak ($ "Hola {Nombre}"); esperará la llamada de 5 segundos.
}
Después del retraso de 5 segundos, el
llama para decir hola está hecho.

Si ejecuta esto y toca el botón, obtendrá el retraso de 5 segundos antes de escuchar el


la aplicación dice hola, y en todo momento la aplicación sigue respondiendo. El método ejecutado por el
El comando es un método asíncrono que espera la llamada a Task.Delay , que a su vez retrasa
durante 5 segundos en un subproceso en segundo plano antes de ejecutar el código para volver a saludar
el hilo de la interfaz de usuario.

5.8 Haz que tu aplicación se sienta receptiva


Como has visto hasta ahora, es relativamente fácil hacer que tu aplicación responda ejecutando
tareas de larga duración en un hilo de fondo. Desafortunadamente, esto no es suficiente para hacer
su aplicación una experiencia de cinco estrellas. No solo necesitas hacer cosas en segundo plano,

Page 179
Haz que tu aplicación se sienta receptiva 149

pero también debe mostrar comentarios visibles al usuario de que algo está sucediendo, así que
ellos saben que necesitan esperar.
Hay algunas formas populares de mostrar comentarios: usando alguna forma de control de ruleta
controle su UI mientras permite que las interacciones del usuario continúen, usando el progreso
diálogos que cubren la pantalla y bloquean la actividad hasta que se completa el progreso, o muestran
ing datos de carga ficticios, como en la figura 5.24. Una aplicación de correo electrónico podría usar todos estos métodos:
ods para mostrar el progreso de diferentes maneras en diferentes momentos. Cuando se inicia la aplicación, lo hará
necesita autenticar al usuario, por lo que podría mostrar datos ficticios mientras esto sucede.
Luego, una vez que haya iniciado sesión, podría mostrar su lista de correo electrónico con una flecha giratoria en la parte superior para
muestra que está cargando más correos electrónicos. Finalmente, si toca un nuevo correo electrónico que no ha sido completamente
descargado, puede mostrar un cuadro de diálogo de progreso, que muestra que está bloqueado de lectura-
ing el correo electrónico hasta que se haya descargado completamente.

Buscar Buscar Buscar


Noticias La gente viaja Noticias La gente viaja Noticias La gente viaja

Cargando…

Lauren Ipsum
Auckland

Amar la playa hoy!

Publicado hace 4 horas Cargando…

Aarti Effem
Wellington

Afuera para comer

Publicado hace 5 horas

Lauren Ipsum
Auckland

Datos de carga ficticios Diálogo de progreso en la parte superior Diálogo de progreso sobre
de la lista siendo recargada toda la pantalla

Figura 5.24 Si su aplicación parece que está haciendo algo durante una operación larga, el usuario
Sé más feliz que si tu aplicación no responde.

La forma en que muestra el progreso al usuario depende en gran medida de su aplicación. En


Android hay una clase ProgressDialog que crea un diálogo que se encuentra en el medio de
la pantalla, muy similar al tercer ejemplo en la figura 5.24. En iOS tienes que

https://translate.googleusercontent.com/translate_f 114/131
23/2/2020 Jim Bennett
enrolle esto o use un componente de terceros, pero tiene una propiedad simple que puede establecer en
muestra una ruleta en la barra de estado. Crear listas pull-to-refresh es fácil en ambas plataformas
formularios: está integrado en los diversos controles de lista o incluido en ayudantes de fácil acceso.
Crear datos de carga ficticios es algo que necesitará escribir usted mismo, ya que sería
específico para su aplicación.
Siempre debe pensar en cómo dar retroalimentación a su usuario cuando trabaja
en el fondo. Si su aplicación parece no estar haciendo nada cuando se está cargando, usted

Page 180
150 C APÍTULO 5 ¿Qué estamos (a) esperando? Una introducción a multihilo para aplicaciones Xamarin

probablemente necesite agregar algunos comentarios de los usuarios. Idealmente, debería escribir este código en una plataforma
clase específica del formulario y exponer la capacidad de mostrar y ocultar indicadores de progreso a través de un
interfaz que pone a disposición de sus modelos de vista a través de IoC, como ITextToSpeech
interfaz en el capítulo 4. De esta manera, sus comandos pueden usarlo para mostrar comentarios, al igual que
en el siguiente pseudocódigo.

Listado 5.21 Mostrar comentarios al usuario durante un comando de ejecución prolongada

Una instancia de IProgressService se pasa a través del constructor


inyección y almacenado en un campo. Esta interfaz tiene plataforma específica
implementaciones para mostrar alguna forma de retroalimentación de progreso al usuario,
y para ocultar esa retroalimentación una vez que se completa la acción de larga duración.

clase pública MyViewModel: MvxViewModel


{
IProgressService progressService;

MyViewModel público (IProgressService progressService)


{
this.progressService = progressService;
DoSomethingLongCommand = new MvxAsyncCommand (() => DoSomethingLong);
}

public ICommand DoSomethingLongCommand {get; conjunto privado;

Tarea asíncrona DoSomethingLong ()


{
progressService.ShowProgressFeedback ();
Antes de una acción de larga duración.
tratar
comienza, la retroalimentación de progreso
{ se muestra al usuario.
...
}
finalmente
{
progressService.HideProgressFeedback ();
}
Una vez completada la acción de larga duración, el
}
La retroalimentación de progreso está oculta. Esto se hace en un
}
finalmente bloquear para que si el comando arroja un
excepción, los comentarios aún están ocultos.

5.9 Es hora de empezar a construir cosas


En los últimos capítulos, hemos pasado por MVVM mirando la plataforma cruzada
modelo y modelo de vista, el enlace y la vista. Hemos visto propiedades modificadas
notificaciones y comandos y visto cómo ejecutar código en múltiples hilos. Estos son
principios importantes que constituyen los cimientos de la construcción de plataformas cruzadas de alta calidad
formar aplicaciones móviles.

Página 181
Resumen 151

Ahora estás listo para comenzar a crear aplicaciones de verdad. En la siguiente parte de este libro vamos a
comience a buscar la creación de una aplicación desde cero, comenzando con el diseño de la aplicación,
la interfaz de usuario, el usuario fluye a través de la aplicación y la estructura del código.

Resumen
En este capítulo aprendiste
▪ Al crear aplicaciones, debe mantener la interfaz de usuario receptiva o los usuarios dejarán de usar
sus aplicaciones Para hacer esto, puede usar tareas para escribir código asincrónico que se ejecuta en
hilos de fondo en lugar de en el hilo principal de la interfaz de usuario.
▪ El hilo de la interfaz de usuario es donde sucede todo en la interfaz de usuario. Excepciones a esto
el hilo puede matar su aplicación, y actualizar la interfaz de usuario desde otro hilo arrojará
excepciones

https://translate.googleusercontent.com/translate_f 115/131
23/2/2020 Jim Bennett
▪C # tiene algunas características increíbles que facilitan la escritura de código limpio que se ejecuta en
el fondo.
▪ Además de mantener su UI receptiva, debe mostrar sus comentarios al usuario
que algo esta pasando

También aprendiste a
▪ Ejecute el código en un subproceso en segundo plano utilizando una tarea .
▪ Use las continuaciones para ejecutar múltiples tareas, incluidas las tareas de cálculo de referencias en
el hilo de la interfaz de usuario.
▪ Manejar excepciones lanzadas dentro de tareas usando continuaciones.
▪ Use async y aguarde para que su código sea más legible.

Page 182

https://translate.googleusercontent.com/translate_f 116/131
23/2/2020 Jim Bennett

Página 183

Parte 2

Construyendo aplicaciones

N hora que ya está familiarizado con el patrón de diseño MVVM y cómo se puede
usado para construir código comprobable y reutilizable, esta parte del libro se expande en ese
conocimiento. Muestra cómo puede crear aplicaciones multiplataforma en iOS y Android,
comenzando con el código multiplataforma y pasando a la IU específica de la plataforma
código, tomando un par de aplicaciones de ejemplo desde el diseño hasta el pleno funcionamiento
aplicaciones Esta parte se mueve hacia arriba, capa por capa, a través de MVVM, antes de sumergirse en el
Interfaces de usuario de Android e iOS.
El Capítulo 6 presenta dos aplicaciones de ejemplo que se construirán en el resto
de esta parte Analiza cómo diseñar una aplicación, centrándose en qué código va en qué
capa en el patrón de diseño MVVM. Finalmente, cubre la creación de soluciones para
aplicaciones de ejemplo y mira el proyecto y las propiedades de la aplicación para un Xamarin
aplicación movil.
El Capítulo 7 se centra en la capa del modelo. Verás cómo construir modelos simples
y capas de modelos más complejas con servicios y repositorios, y aprenderá
Cómo acceder a bases de datos SQLite y servicios web. También presenta pruebas unitarias,
mostrando lo fácil que es probar un código bien estructurado.
El Capítulo 8 sube una capa y cubre los modelos de vista. Considera cómo el estado
y el comportamiento están representados, cubriendo propiedades, comandos y valores
versión. También muestra cómo probar la lógica de la interfaz de usuario mediante pruebas unitarias.
Los capítulos 9 y 10 cubren las capas de vista y aplicación en Android, reciclador
vistas para mostrar listas de datos y navegación multipantalla. Luego muestra cómo
agregue brillo a una aplicación creando íconos y pantallas de bienvenida.
Los capítulos 11 y 12 se centran en iOS, trabajando en la aplicación y visualizando capas
de la primera aplicación de ejemplo, que abarca controladores de vista, controles de IU, guiones gráficos y

Page 184
154 P ART 2 Creación de aplicaciones

diseño automático y restricciones, vistas de tabla y navegación multipantalla. Luego cubre


íconos de aplicaciones y pantallas de inicio.
Una vez que haya terminado estos capítulos, tendrá aplicaciones iOS y Android en funcionamiento.
eso estará listo para producción en la tercera parte de este libro.

https://translate.googleusercontent.com/translate_f 117/131
23/2/2020 Jim Bennett

Page 185

Este capítulo cubre


▪ Preparación
diferencias entre iOS y Android
▪ Diseñar
aplicaciones multiplataforma

para crear aplicaciones multiplataforma teniendo en cuenta


6
los flujos que un usuario tomará en una aplicación, incluyendo cuáles
capa y qué hilo usar
▪ Crear la solución para una aplicación
Diseñando MVV

▪ Configurarlas propiedades de su aplicación, incluido SDK


versiones y configuraciones del enlazador

En la primera parte de este libro, analizamos los fundamentos de una investigación cruzada basada en MVVM.
aplicación móvil de plataforma. Observamos de qué se tratan las diferentes capas en MVVM
y cómo estructurar su código dentro de ellos. También vimos cómo funcionan los hilos en
aplicaciones móviles y cómo puede mantener sus aplicaciones receptivas cuando se realiza durante mucho tiempo
ejecutando acciones. Ahora es el momento de pensar cómo puedes comenzar a construir una cruz
aplicación móvil de plataforma.
Como desarrolladores, a menudo nos sentimos tentados a iniciar una nueva aplicación activando nuestro IDE y
haciendo clic en Archivo> Nuevo proyecto. Pero un poco de planificación es muy útil, así que antes de comenzar

155

https://translate.googleusercontent.com/translate_f 118/131
23/2/2020 Jim Bennett
Página 186156 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

creando cualquier código, primero pensemos en lo que estamos construyendo y luego pensemos en
cómo construirlo Entonces podemos crear una nueva solución y ver cómo difiere de la
tipos de soluciones a las que la mayoría de los desarrolladores de C # están acostumbrados.
A lo largo de esta parte del libro veremos dos ejemplos de aplicaciones, uno muy
simple y un poco más complejo, y usaré estas aplicaciones para presentar las ideas
y conceptos que necesitará saber para crear aplicaciones multiplataforma con calidad de producción
usando Xamarin y MVVM. En este capítulo hablaremos sobre el diseño de estas aplicaciones:
verá cómo crear las soluciones para ellos, y explicaré estas soluciones en
detalle. Los próximos capítulos explicarán cómo puede construir sus aplicaciones Xamarin
capa por capa, desde el modelo, al modelo de vista, a la vista, mirando nuestros dos exámenes
aplicaciones completas y otras características que puede agregar a sus aplicaciones en cada capa.

6.1 Introducción al diseño de una aplicación multiplataforma


La aplicación de Facebook es popular en iOS y Android, y atiende a millones de usuarios en todo el mundo.
amplio. En ambas plataformas ofrece la misma funcionalidad, pero la forma en que ofrece sus características
Tures es diferente en cada plataforma. La Figura 6.1 muestra cómo se ven estas aplicaciones en
hora de escribir.

Facebook en Android Facebook en iOS

Buscar Buscar

En Vivo Foto Registrarse

¿Qué tienes en mente?


¿Qué tienes en mente?

ESTADO FOTO REGISTRARSE

Figura 6.1 Las aplicaciones como Facebook se ven y funcionan de manera diferente en iOS y Android.

En Android, todos los botones están en la parte superior de la pantalla. Esto se debe a que Android tiene
sus tres botones de navegación en la parte inferior del dispositivo, ya sea físico o software
botones. Si una aplicación tiene botones justo encima de estos botones de navegación, es demasiado fácil aceptar
toque dentalmente un botón de navegación cuando tenía la intención de tocar un botón de aplicación, por lo que Android
Las aplicaciones no tienen botones en la parte inferior como una buena práctica de diseño.
iOS, por otro lado, no tiene botones fáciles de tocar en la parte inferior, tiene un
botón de inicio del hardware, lo que permite que la aplicación iOS de Facebook tenga algunos de sus botones activados
El fondo. Estos botones se utilizan para seleccionar diferentes vistas: su fuente de noticias, mercado-
lugar, notificaciones y configuraciones. Son botones de tabulación, cada uno representa un
nueva pestaña en un control de pestaña. (Los controles de pestañas consisten en varias páginas indicadas por pestañas

Page 187
Introducción al diseño de una aplicación multiplataforma 157

botones en una barra, y al tocar un botón de pestaña muestra la página representada por esa pestaña, sim-
ilar a las pestañas de las carpetas en un archivador).
En Android, deslizar de derecha a izquierda o de izquierda a derecha cambia las pestañas; deslizar en iOS
no cambiará las pestañas, pero deslizar en la aplicación de Facebook deslizará la pantalla hacia afuera para mostrar
la pantalla de Messenger (haciendo que parezca que la pantalla de Messenger está debajo de la pantalla principal
pantalla: siguiendo las pautas de la interfaz humana de iOS sobre profundidad). Este es un simple pero
diferencia importante: Android tiene pestañas en la parte superior con deslizar para cambiar pestañas,
mientras que iOS tiene pestañas en la parte inferior sin deslizar.
Estas diferencias pueden parecer pequeñas, pero son importantes. Implican la navegación
paradigmas que son comunes a cada plataforma, haciendo que las aplicaciones sean consistentes con otras
aplicaciones en sus propias plataformas, ya sean aplicaciones que vienen con el sistema operativo o de
terceros. Esto significa que un nuevo usuario puede comenzar a usar una aplicación y ya tiene una idea
cómo navegarlo
Con Xamarin puedes crear una aplicación para múltiples plataformas en un Visual Studio
solución con mucho código compartido, pero debe tener cuidado con sus IU. Tú
no siempre debe crear aplicaciones idénticas en ambas plataformas; en su lugar, adapte el usuario inter-
experiencia facial y de usuario en cada plataforma. Querrás maximizar la reutilización del código, pero
no necesariamente reutiliza las mismas IU.
Afortunadamente, parte de esta complejidad se abstrae de ti, si creas pestañas en
sus aplicaciones usando controles de pestaña listos para usar, obtendrá el comportamiento apropiado, como
se muestra en la figura 6.2. Los problemas vienen cuando necesitas algo que no viene
desde un control listo para usar.

Pestañas en Android Pestañas en iOS

MyApp MyApp

Noticias Clima

https://translate.googleusercontent.com/translate_f 119/131
23/2/2020 Jim Bennett

Figura 6.2 El uso de controles listos para usar garantiza que su aplicación tendrá una apariencia consistente
con el resto del sistema operativo.

Google ha lanzado una aplicación de Gmail para Android e iOS (figura 6.3). En iOS, para
escribe un nuevo correo electrónico toca un botón en la barra de herramientas superior. Esto es bastante estándar para iOS
aplicaciones, usando la barra de herramientas superior para botones de acción. En Android hace algo diferente.
ent: en lugar de tener un botón en la barra de herramientas superior, tiene un botón de acción flotante
(FAB) Este es un botón redondo cerca de la parte inferior derecha de la pantalla (un poco más arriba de
la parte inferior para evitar el riesgo de tocar accidentalmente un botón de navegación), y utiliza un

Page 188
158 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

Gmail en Android Gmail en iOS

Bandeja de entrada Bandeja de entrada

Beto Hola de bob Beto Hola de bob

Mamá Feliz cumpleaños Mamá Feliz cumpleaños

Figura 6.3 Android e iOS tienen diferentes paradigmas para la acción más popular que un usuario
podría hacerlo: iOS usa botones de la barra de herramientas, mientras que Android favorece el botón de acción flotante.

efecto de sombra (denominado elevación en Android-speak) para que parezca que está flotando
encima de la página Este es un paradigma estándar de la interfaz de usuario de Android: muchas aplicaciones de Android usan un
FAB para la acción más común en una pantalla en particular.

Las aplicaciones móviles cambian constantemente


Al momento de escribir, Gmail usa el botón de la barra de herramientas de iOS y Android FAB. Esto puede
cambio en futuras versiones porque Google realmente está tratando de impulsar su propio diseño
estándar. Vale la pena obtener algunas aplicaciones en diferentes plataformas y ver sus diferentes
para obtener una comprensión de cómo las aplicaciones pueden proporcionar la misma funcionalidad en
diferentes caminos.

Android también ha lanzado un componente de navegación inferior, para proporcionar pestañas similares a iOS
en el fondo. Esto es bastante reciente, pero puede significar que las aplicaciones de Android comenzarán a
Soporte de navegación inferior.

Estas diferencias no se proporcionan de forma gratuita mediante controles listos para usar. En cambio, son
diferentes controles agregados de diferentes maneras. En iOS, los desarrolladores tuvieron que explícitamente
agregar un botón de barra de herramientas, y en Android tuvieron que agregar el FAB.
Como desarrolladores de aplicaciones multiplataforma, debemos tener en cuenta estas diferencias.
Como consumidor, es fácil usar una plataforma y acostumbrarse a la forma en que funciona, pero ser
un desarrollador multiplataforma exitoso, necesitará acostumbrarse a ambas plataformas para que pueda
siempre puede pensar en sus interfaces de usuario en términos de cada plataforma.

Page 189
Diseñando la UI y los flujos de usuarios 159

Con esto en mente, ahora comencemos a pensar en el diseño de un par de aplicaciones.


Una será una calculadora de raíz cuadrada de una sola pantalla. El otro será un multipantalla
aplicación de contador (una aplicación que puedes usar para contar diferentes cosas, como cuántas tazas de
café que has tomado). Llevaremos ambas aplicaciones desde el diseño hasta mirar el

https://translate.googleusercontent.com/translate_f 120/131
23/2/2020 Jim Bennett
estructura del código, para crear una nueva solución y estructurar el código.
6.2 Diseñando la UI y los flujos de usuarios
Para el resto de esto y los próximos capítulos, vamos a centrar nuestra atención en
Un par de ejemplos de aplicaciones. Uno es una calculadora de raíz cuadrada simple (como el ejemplo
del capítulo 2), que llamaremos SquareRt, de acuerdo con la tendencia actual de nam-
ing cosas tomando palabras normales y perdiendo vocales. La otra será una aplicación de contador
admite múltiples contadores, y llamaremos a este Countr. Veamos esto en
gire y considere el diseño de sus interfaces de usuario y flujos de usuarios. Más tarde verás cómo esto
mapas a la arquitectura de cada aplicación.
Cuando me refiero a la interfaz de usuario , me refiero a la interfaz de usuario presentada al usuario. Por
el usuario fluye , me refiero a la experiencia del usuario: las acciones que el usuario puede tomar para fluir
a través de la aplicación, las interacciones que tienen con la interfaz de usuario y los resultados de estos
acciones en pantalla.

6.2.1 SquareRt: una aplicación sencilla para calcular raíces cuadradas


El objetivo de esta aplicación es permitir que el usuario ingrese un número y luego calcular su cuadrado
raíz. Es una tarea bastante simple, por lo que no necesitamos una interfaz de usuario compleja. Este es también el tipo de
aplicación que podría ser la misma tanto en iOS como en Android.

Apple requiere aplicaciones de alta calidad


Este es un ejemplo de aplicación simple para ilustración, y no es algo que deba
compilar e intentar enviar a las tiendas de aplicaciones. Google tiene una actitud bastante laxa hacia el
calidad de las aplicaciones que se pueden enviar, mientras que Apple es bastante draconiana (aunque
ambos son estrictos sobre material ofensivo o violaciones de derechos de autor). Si tu aplicación no funciona
cualquier cosa de valor (como calcular una raíz cuadrada), es muy probable que sea rechazada
de la tienda de aplicaciones. De acuerdo con las pautas de la tienda de aplicaciones de Apple, hay "muchos
Desarrolladores que no desean que sus aplicaciones de calidad estén rodeadas de horas de aficionados ".

Puede leer las "Pautas de revisión de la tienda de aplicaciones" de Apple en http://mng.bz/525T . los
Las pautas de Google están en http://mng.bz/KQbE .

Antes de que podamos comenzar a cortar el código, debemos pensar qué construir. Pensando
sobre la interfaz de usuario es una buena manera de dividir el código. Estamos usando MVVM después de todo, así que
debe tener en cuenta la capa del modelo, las vistas y sus modelos de vista correspondientes.
Una vez que sepamos qué interfaz de usuario necesitamos, podemos comenzar a definir nuestras vistas, y luego la vista
modelos.

Page 190
160 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

Una buena manera de definir la interfaz de usuario es pensar en los flujos de usuarios, qué acciones realiza el usuario
querrá tomar, y cuáles serán los resultados de estas acciones. Una vez que tengas estos
acciones, puede comenzar a asignarlas a la interfaz de usuario y definir cómo debería ser su interfaz de usuario.
Dibujemos un diagrama de flujo simple del único flujo de usuarios a través de la aplicación SquareRt, que se muestra
en la figura 6.4.

Figura 6.4 La aplicación SquareRt es bonita


El usuario ingresa Raíz cuadrada La respuesta es
simple, con un solo flujo que el usuario
un número es calculado se muestra en la interfaz de usuario
puede tomar.

Este flujo es muy simple: el usuario solo puede usar esta aplicación para una cosa. Necesitan un camino
para ingresar un número, algo en la aplicación necesita calcular la raíz cuadrada, y luego
la raíz cuadrada se presenta al usuario. La interfaz de usuario para esto es relativamente fácil de imaginar:
necesita una forma de ingresar el número, una forma de iniciar el cálculo y una forma de
mostrar los resultados La Figura 6.5 muestra algunas opciones.

SquareRt SquareRt SquareRt

400

20

√ √ 400
20

20
√ 400

Raíz cuadrada Calcular

Figura 6.5 Algunas IU posibles para SquareRt, una raíz cuadrada simple
aplicación de cálculo

Las dos primeras IU en la figura 6.5 tienen un cuadro de texto donde el usuario SquareRt
puede ingresar el número y un botón que inicia el cálculo
Lation. El tercero elimina el botón, desde una perspectiva de usuario
tive, si están ingresando un número, obviamente quieren ver
la raíz cuadrada, para que la aplicación pueda calcularla automáticamente 20

https://translate.googleusercontent.com/translate_f √ 121/131
23/2/2020 Jim Bennett


400
cada vez que cambia el valor en el cuadro de texto. Esta es una buena
opción a considerar: cuanto menos tenga que hacer el usuario, mejor
la experiencia.
Vamos a usar la tercera interfaz de usuario en este libro (figura 6.6),
pero es un buen ejercicio pensar en las otras interfaces de usuario o
eche un vistazo a otros diseños propios, a medida que profundizamos en Figura 6.6 Nuestra interfaz de usuario final
diseñando esta aplicación para la aplicación SquareRt

Página 191
Diseñando la UI y los flujos de usuarios 161

6.2.2 Countr: una aplicación para contar varias cosas


La aplicación SquareRt es un ejemplo muy simple, pero la mayoría de las aplicaciones son mucho más complicadas.
Nuestro segundo ejemplo es una aplicación llamada Countr que permite al usuario definir múltiples
contadores, e incrementarlos cuando lo deseen, como rastrear el número de
tazas de café que tomaron o la cantidad de veces que salieron a correr. Esta
la aplicación deberá mostrar varios contadores, necesitará la capacidad de agregar o eliminar un
contador, y necesitará una forma simple de incrementar cada contador. La Figura 6.7 muestra estos
El usuario fluye.

Los contadores son


El usuario quiere Todos los contadores son
cargado desde
ver contadores se muestra en la interfaz de usuario
almacenamiento

El contador es
El usuario agrega El usuario ingresa Nuevo contador es
creado y
un contador detalles del contador se muestra en la interfaz de usuario
almacenado

El contador es El contador es
El usuario elimina
retirado de remoto
un contador
almacenamiento de la interfaz de usuario

El contador es El contador es
Incrementos de usuario
incrementado actualizado en
un contador
y almacenado la interfaz de usuario

Figura 6.7 El usuario fluye para la aplicación Countr: muestra, agrega, elimina y
contadores incrementales

Mostrar listas es algo muy popular en las aplicaciones móviles. Piensa en las aplicaciones que
se usan con mayor frecuencia, probablemente la mayoría de ellos tratan con listas o cuadrículas de datos. Aplicaciones de correo electrónico
muestra una lista de correos electrónicos, Facebook muestra una lista de publicaciones, Twitter muestra una lista de tweets, mes-
Las aplicaciones de almacenamiento como WhatsApp muestran listas de mensajes. En todas estas aplicaciones tienes un scrolla-
lista de datos flexible. Usted lee lo que hay en la página y luego "empuja" los elementos deslizando hacia arriba
arriba en la pantalla para ver qué hay debajo. Este es un paradigma popular, así que lo usaremos para nuestro
Aplicación Countr, con la parte principal de la interfaz de usuario que muestra una lista de contadores.
Como ya has visto, Gmail en iOS y Android tienen diferentes formas para el usuario
para crear un nuevo correo electrónico: un botón de barra de herramientas en iOS y un FAB en Android. Seguiremos
esta convención en nuestra aplicación con la versión de iOS que tiene un botón de barra de herramientas para agregar un nuevo
contador, y la versión de Android que tiene un FAB para hacer lo mismo.
A menudo, las aplicaciones con listas usan deslizar para eliminar: las aplicaciones de correo electrónico le permiten deslizar un correo electrónico
a la izquierda para mostrar un botón Eliminar debajo del correo electrónico, que puede tocar para eliminar. Esta
paradigma sería bueno para eliminar contadores.
Otra cosa que ves con las listas son los botones de cada elemento, lo que te permite
formar alguna acción, como retuitear un tweet en la aplicación de Twitter o darle me gusta a una publicación en

192
162 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

Facebook. Nuevamente, este es un paradigma popular, por lo que lo usaremos en nuestra aplicación Countr para
Incrementar un contador.
A diferencia de nuestra aplicación SquareRt simple, la aplicación Countr tendrá diferentes IU en
iOS y Android, al menos cuando se trata de agregar contadores. Esto es algo que tu
siempre debe tenerlo en cuenta: Xamarin le permite crear aplicaciones multiplataforma, pero
siempre debe construir las interfaces de usuario de una manera adecuada para cada plataforma. Multiplataforma
núcleo y una interfaz de usuario específica de la plataforma. No caigas en la tentación de crear una interfaz de usuario para ambas plataformas.
formularios: si va en contra de la interfaz de usuario estándar de una plataforma, solo confundirá a los usuarios.
La Figura 6.8 muestra las diferentes UI que podemos usar para esta aplicación en iOS y
Androide.

iOS Androide

https://translate.googleusercontent.com/translate_f 122/131
23/2/2020 Jim Bennett
Countr Añadir Cancelar Nuevo contador hecho Countr Nuevo mostrador

Cafés 44 + Cafés 44 +
Nombre del contador Nombre del contador
Carreras 1 + Carreras 1 +
Toque Agregar Toca +

Figura 6.8 UI de iOS y Android para la aplicación Countr con diferentes convenciones de IU en cada plataforma,
como un botón Agregar en la barra de herramientas en iOS, pero un FAB en Android

6.2.3 Definición de flujos de usuario y UI


Acabamos de ver los flujos de usuarios para nuestras dos aplicaciones de ejemplo. Pero la parte difícil puede ser
definiendo estos flujos, entonces, ¿cómo lo haces? Me gusta usar estos pasos:
1 Comience por pensar en las acciones de alto nivel que el usuario querrá usar
aplicación para, como contar algo.
2 A partir de estas acciones de alto nivel, piense en cómo pueden obtener la aplicación en un estado
donde pueden realizar estas acciones, como agregar un contador para que puedan
contar algo y mostrar todos los contadores para ver qué pueden contar.
3 Piense en las tareas auxiliares que tal vez quieran realizar en este estado,
como eliminar un contador.
44 Piense en los pasos que da el usuario para realizar cada tarea o acción, como
ver los contadores y los resultados finales, como ver los contadores.
55 Piense en las tareas generales que debe realizar su aplicación para pasar de
punto de partida para el resultado final, como cargar contadores desde algún tipo de
almacenamiento.

Siguiendo estos pasos, debería poder construir algunos diagramas de flujo simples para su
aplicación, como las que ya has visto. El diagrama de flujo debe comenzar con el nivel alto

Página 193
Diseñando la UI y los flujos de usuarios 163

acción que el usuario intenta lograr, comenzando desde el lugar de su aplicación donde el usuario
probablemente será cuando inicien estas acciones. Entonces debe pasar por uno o más
pasos para lograr esta acción, ya sea pasos basados en el usuario (algo que el usuario tiene que hacer) o
pasos del sistema (algo que hace la aplicación). Finalmente, termina con un resultado que puede o puede
No involucrar al usuario.
La figura 6.9 muestra un ejemplo simple. El usuario quiere ver contadores, y el final
El resultado es que se muestran los contadores. El paso requerido para llegar allí es cargar contadores
de almacenamiento.

Figura 6.9 Los pasos para mostrar


Los contadores son Todos los contadores contadores: el usuario quiere verlos,
El usuario quiere
cargado desde son exhibidos
ver contadores la aplicación los carga, la aplicación muestra
almacenamiento en la interfaz de usuario
ellos al usuario.

Una vez que tenga estos flujos, es fácil comenzar a asignarlos a una interfaz de usuario. Tu IU necesita
proporcionar una manera de iniciar cada flujo y proporcionar el resultado. En este ejemplo, la interfaz de usuario
necesita una manera de comenzar a cargar los contadores desde algún tipo de almacenamiento cuando es
abierto y luego mostrando todos los contadores. Esto significa que necesita una interfaz de usuario con un control
que puede mostrar una recopilación de datos, y la forma normal de hacerlo es mediante una vertical
control de lista de desplazamiento. Cuando estás pensando en cómo representar tareas y resultados
en la interfaz de usuario de su aplicación, eche un vistazo a cómo lo hacen otras aplicaciones, a veces hay estándares
formas, como listas, que puede usar para hacer que su aplicación sea fácil de usar. Después de todo, si estás usando
un paradigma de UI popular, sus usuarios probablemente ya estén acostumbrados, por lo que estarán
cómodo en tu aplicación.
El ejemplo de Countr demuestra que puede crear aplicaciones multiplataforma que
tienen los mismos flujos de usuarios, pero con diferentes IU. No puedo enfatizar lo suficiente lo importante que es
es considerar siempre las diferencias entre los paradigmas de UI en iOS y Android.
Con Xamarin, puede crear aplicaciones multiplataforma, pero eso no significa que sus aplicaciones
tiene que ser exactamente igual en ambas plataformas. Vale la pena pasar tiempo para llegar a
sepa cómo funciona cada plataforma para que cuando diseñe sus aplicaciones, pueda conservarlas
diferencias en mente, incluso si la diferencia es tan simple como usar un FAB en Android
y un botón de barra de herramientas en iOS.
Hay muchas opiniones sobre cómo construir una aplicación móvil con una buena experiencia de usuario
rience: el tema es digno de un libro por derecho propio (como la usabilidad importa de Matt
Lacey, Manning, mayo de 2018), pero como un simple punto de partida, recomiendo mirar
su aplicación de la forma en que hemos visto nuestros dos ejemplos. Comience considerando al usuario
flujos: piense en las interacciones que su usuario tendrá con su aplicación. Entonces piensa
acerca de cómo puede asignar esas interacciones a la interfaz de usuario de una manera que tenga sentido en cada
plataforma. También es bueno pensar en cómo el usuario puede lograr cada flujo en tan pocos
pasos como sea posible, de una manera que tenga sentido en cada plataforma.
Ahora hemos diseñado los flujos de usuarios y esbozado las interfaces de usuario, así que echemos un vistazo a
convirtiéndolos en una arquitectura que sigue el patrón de diseño MVVM.

https://translate.googleusercontent.com/translate_f 123/131
23/2/2020 Jim Bennett

Página 194
164 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

6.3 Diseñando la aplicación


Ahora que hemos resuelto lo que la interfaz de usuario iOS Androide

debería ser, es hora de empezar a pensar C# C#


App
la arquitectura. Como has visto en el pre
capa
cediendo capítulos, hay tres capas y C # (.NET Standard)

dos tipos de hilos para pensar. Tienes que


considere lo que pasa en la capa del modelo, C#
Capa de interfaz de usuario C# Ver

lo que va en la capa del modelo de vista, y Unión


lo que pasa en la capa de vista. Y para el
Lógica de la interfaz de usuario Ver
código en el modelo y las capas de modelo de vista, capa
C # (.NET Standard)
modelo

debes considerar qué código necesita


ejecutar en el hilo de la interfaz de usuario y lo que puede ejecutarse en
el fondo. Negocio
C # (.NET Standard) Modelo
capa lógica

6.3.1 Cual capa


Cuando empiezas a pensar en la estructura de
su código, debe considerar qué lay- Figura 6.10 MVVM tiene tres capas, con el
la capa de vista es específica de la plataforma y la vista
Luego entran las diferentes partes del código.
El modelo y las capas de modelo son multiplataforma.
Piense en los diagramas de capa de pre
capítulos viciosos, como se muestra en la figura 6.10.
Recuerde que el código responsable de las interacciones de la interfaz de usuario abarca la capa de vista,
la capa del modelo de vista y el enlace: la vista son los widgets de IU específicos de la plataforma,
y el modelo de vista es la lógica de interfaz de usuario multiplataforma vinculada a la vista.
S QUARE R T
Para SquareRT, queremos la mayor cantidad de código posible en el modelo y en las capas de modelo de vista.
Este es un código multiplataforma que se comparte entre las aplicaciones de Android e iOS, y nosotros
solo quiero escribirlo una vez y reutilizarlo en ambas plataformas.
Veamos cómo se puede dividir el código de la aplicación SquareRt entre capas. Podemos llevar al usuario
flujo que hemos definido y mapearlo a través de las capas. Esto se muestra en la figura 6.11.
Lo que vemos de este ejercicio es que necesitamos una vista con un control que un usuario
puede ingresar texto y un control para mostrar el resultado. También necesitamos un correspondiente
ver el modelo que puede unirse a esos controles y una capa de modelo que puede hacer el cálculo
ción Esto lleva rápidamente a tres clases que son la estructura principal de nuestra aplicación, como
se muestra en la figura 6.12.
C OUNTR
Repitamos el mismo ejercicio con nuestra aplicación Countr, mapeando los flujos que ya hemos
definido en nuestras tres capas MVVM. Esto se muestra en las figuras 6.13 y 6.14.

Página 195
Diseñando la aplicación 165

iOS Androide

App C# C#

capa
C # (.NET Standard)

C#
Capa de interfaz de usuario C# Ver

Unión
El usuario ingresa La respuesta es
Lógica de la interfaz de usuario Ver un número se muestra en la interfaz de usuario
C # (.NET Standard)
capa modelo

Negocio Raíz cuadrada


C # (.NET Standard) Modelo
capa lógica es calculado

Figura 6.11 Los flujos de usuarios pueden correlacionarse con las capas MVVM, con interacciones del usuario
que abarca la vista y las capas del modelo de vista.

iOS Androide

App C# C#
capa

https://translate.googleusercontent.com/translate_f 124/131
23/2/2020 Jim Bennett
C # (.NET Standard)

Capa de interfaz de usuario


C# C# Ver SquareRtView

Unión El usuario ingresa La respuesta es


Lógica de la interfaz de usuario Ver un número se muestra en la interfaz de usuario
C # (.NET Standard) SquareRtViewModel
capa modelo

Negocio Raíz cuadrada


C # (.NET Standard) Modelo SquareRtCalculator
capa lógica es calculado

Figura 6.12 Una vez que haya asignado los flujos de usuarios a las capas MVVM, también puede asignar clases a estos.

Ver

Todos los contadores Nuevo mostrador


El usuario quiere El usuario agrega El usuario ingresa
son exhibidos se muestra
Ver ver contadores un contador detalles del contador
en la interfaz de usuario en la interfaz de usuario
modelo

Los contadores son El contador es


Modelo cargado desde creado y
almacenamiento almacenado

Figura 6.13 Asignación que muestra y agrega contadores a las capas de vista, modelo de vista y modelo

Página 196
166 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

Ver

El contador es Usuario El contador es


El usuario elimina
remoto incrementos actualizado
Ver un contador
de la lista un contador en la interfaz de usuario
modelo

Contadores es El contador es
Modelo remoto incrementado
de almacenamiento y almacenado

Figura 6.14 Asignación de incrementos y eliminación de contadores a la vista, modelo de vista y


capas modelo

Nuevamente, al igual que con SquareRt, puede ver un patrón de clases en estas capas. Nosotros necesitamos
para mostrar una lista de contadores que se pueden manipular (como agregar y eliminar
ellos), por lo que necesitamos una vista y un modelo de vista para la interfaz de usuario, así como algún tipo de servicio
clase en la capa del modelo que almacena y recupera los contadores de algún tipo de almacenamiento
años. También necesitamos algo en la interfaz de usuario para agregar un nuevo contador e ingresar sus detalles, por lo que
Necesitamos una vista y un modelo de vista para este nuevo contador. Esto nos da las clases que se muestran en
figura 6.15.

Ver CountersView CounterView

Ver
CountersViewModel CounterViewModel
modelo

Servicio de mostradores Figura 6.15 Los mapas de la aplicación Countr


Modelo a un conjunto de vista, modelo de vista y
Mostrador clases de capa modelo.

D APLICACIÓN DE APLICACIONES EN CAPAS


Una vez que haya resuelto sus flujos de usuario, debería ser obvio qué partes del flujo
implican la interfaz de usuario y qué partes no. Cualquier interacción directa con el usuario necesita algo de
tipo de interfaz de usuario, y cualquier otra cosa no. Esto significa que es relativamente simple mapear al usuario
fluye a las capas MVVM. Cualquier cosa que implique la interfaz de usuario vive en la vista y en la vista.
capas de modelo (la interfaz de usuario en la capa de vista, y el estado y el comportamiento en los modelos de vista), y
La lógica empresarial central vive en la capa del modelo. Su flujo podría cambiar entre capas como
tantas veces como sea necesario: el usuario hace x , la aplicación hace y en segundo plano, le pide al usuario que
confirme en el hilo de la interfaz de usuario, haga z en segundo plano y luego muestre al usuario un resultado.
El proceso de agregar un contador necesita algo en la capa de IU que el usuario pueda
interactuar con para iniciar el flujo de agregar, como un botón Agregar en la vista y un comando
para manejarlo en un modelo de vista. A continuación, el usuario debe asignarle un nombre al contador, por lo que
debe ser algún tipo de interfaz de usuario, como una nueva pantalla con un cuadro de texto donde el usuario pueda
ingrese el nombre y el modelo de vista correspondiente para obtener este nombre. Entonces la aplicación
necesita crear el contador y almacenarlo en algún lugar, y esto se maneja en el modelo
capa. Finalmente, el usuario necesita ver el nuevo contador en la lista, por lo que la IU para mostrar

https://translate.googleusercontent.com/translate_f 125/131
23/2/2020 Jim Bennett
Page 197
Diseñando la aplicación 167

la lista de contadores debe actualizarse, lo que significa una actualización en una lista de contadores
almacenado en un modelo de vista, que se refleja en una vista.

6.3.2 Cual hilo?


Hemos dividido nuestras aplicaciones de ejemplo en capas para que coincidan con el patrón de diseño MVVM, por lo que
Lo siguiente que debe hacer es pensar en subprocesos múltiples. Como viste en el capítulo anterior,
es importante que nuestra aplicación siga respondiendo, por lo que deberíamos comenzar a pensar ahora en
en qué hilo se ejecuta nuestro código.
Hay una regla muy simple a seguir aquí: si la interfaz de usuario se retrasa o no responde
Más de unos 200 ms, el usuario notará un retraso perceptible. Más que esto y eso
se siente como si la aplicación se hubiera bloqueado, y puede tomar solo unos segundos antes de que un usuario sea alimentado
esperando y mata tu aplicación. Siempre debe ejecutar cualquier acción que pueda tomar más
que aproximadamente 100 ms en un hilo de fondo.
Por supuesto, esto no siempre es fácil de juzgar, especialmente cuando estás en el proceso de
desarrollando tu aplicación. La mayoría de los desarrolladores tienen versiones de alta potencia de los últimos y
mejores dispositivos, pero la mayoría de los usuarios no. Lo que lleva 50 ms en tu gama alta
El iPhone 7 puede tardar 500 ms en un viejo iPhone 4s. Hacer una llamada web podría ser casi
instantáneo al llamar a un servicio web de desarrollo que se ejecuta en su desarrollo
máquina y acceder a ella a través de WiFi, pero puede tardar varios segundos en la realidad
mundo usando 3G.
Aquí hay algunas buenas pautas básicas:
1 Siempre pruebe en un dispositivo deficiente; puede recoger dispositivos más antiguos por poco
dinero, ya sea a través de ventas de liquidación o de segunda mano de sitios como eBay o
Craigslist. Vale la pena tener un dispositivo con las especificaciones más bajas que desea admitir
para las pruebas.
2 Siempre asuma que todo lo relacionado con la red se ejecutará lentamente, así que siempre haga
llamadas de red en un hilo de fondo.
3 Al almacenar algo localmente, o recuperar cualquier cosa de una base de datos como
SQLite (una base de datos móvil popular que viene como parte de iOS y Android) o
desde un archivo, siempre haz esto en segundo plano.
44 Si no está seguro, hágalo en segundo plano.

Una buena forma de averiguar qué código debe ejecutarse en el subproceso de interfaz de usuario o en un fondo
el hilo es tomar cada tarea y hacerse algunas preguntas: ¿involucra la interfaz de usuario?
necesita recursos externos, ¿es lento? La Figura 6.16 muestra un diagrama de flujo para esto.
Si asigna los flujos de sus usuarios siguiendo este diagrama de flujo, debería poder fácilmente
averiguar en qué hilo se debe ejecutar su código.

ANDROID TIENE UNA HERRAMIENTA QUE PUEDE AYUDAR A VERIFICAR SU CÓDIGO Android tiene un estricto
modo que puede habilitar para obtener comentarios sobre su código, para ver si se está ejecutando
en el hilo correcto Puede usar esto para obtener comentarios sobre si un
La acción está tardando demasiado en el hilo de la interfaz de usuario. Hay más detalles sobre Strict-
Modo en la referencia del desarrollador de Android: http://mng.bz/nDI5 .

Página 198
168 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

¿Esto usa ¿Esto toma UI hilo o


Haz esto No No No
recursos externos más de 100 ms antecedentes
involucrar a la interfaz de usuario?
(DB, web)? en un dispositivo lento? hilo

si si si

Antecedentes Antecedentes
Subproceso de interfaz de usuario
hilo hilo

Figura 6.16 Si su código involucra la interfaz de usuario, debe ejecutarse en el hilo de la interfaz de usuario, pero si usa un código externo
recursos o es lento, debe ejecutarse en un hilo de fondo.

Cuando se usa código de terceros, como paquetes NuGet o componentes Xamarin, es


siempre es bueno verificar si el código tiene algún método asíncrono. Por ejemplo, si tu
use HttpClient del espacio de nombres System.Net.Http en .NET Framework,
ve que tiene métodos como GetAsync , que devuelve una tarea <HttpResponseMessage> .
Cada vez que se expone un método asíncrono, generalmente puede estar seguro de que internamente lo hará
crear una tarea para ejecutar acciones de larga duración en un hilo de fondo. Puedes esperar esto
desde el hilo de la interfaz de usuario, y su aplicación debe seguir respondiendo porque el HttpClient
maneja el enhebrado por ti. Obviamente, no hay garantías, por lo que es bueno
Verifique el comportamiento primero.
Ahora pensemos en los requisitos de subprocesamiento de nuestras aplicaciones de ejemplo. Tomaremos
cada usuario fluya y considere lo que debe suceder para lograrlo. A partir de ahí, podemos
averiguar si cada parte del flujo necesita ejecutarse en un hilo de fondo.
S QUARE R T
El flujo de usuarios para la aplicación SquareRt tiene tres partes, dos que involucran la interfaz de usuario (obtener
el número inicial y mostrando el resultado), y uno que implica un cálculo.

https://translate.googleusercontent.com/translate_f 126/131
23/2/2020 Jim Bennett
Aunque este es un cálculo relativamente complejo, es bastante rápido: se ejecutará en frac-
de milisegundos, por lo que no tenemos que pensar en hilos de fondo en absoluto.
Todo puede ejecutarse en el hilo de la interfaz de usuario (figura 6.17).
C OUNTR
A diferencia de SquareRt, Countr hace un poco más que un simple cálculo. Incluye un
cálculo simple: incrementar un contador, que podría ejecutarse en el hilo de la interfaz de usuario

El usuario ingresa Raíz cuadrada La respuesta es


Subproceso de interfaz de usuario
un número es calculado se muestra en la interfaz de usuario

Antecedentes
hilo

Figura 6.17 La aplicación SquareRt no hace nada que deba ejecutarse en un


hilo de fondo.

Page 199
Diseñando la aplicación 169

sin ningún problema, pero "almacenamiento" es la palabra clave en estos flujos de usuarios al pensar
acerca de enhebrar. Todavía no hemos discutido el almacenamiento de datos (veremos el almacenamiento en
el siguiente capítulo), pero cualquier tipo de almacenamiento implica hacer una llamada a algo potencial
Tialmente lento. Si escribe en una base de datos SQLite, en un archivo o en un servicio web, es una buena práctica.
tice hacerlo en un hilo de fondo para proteger su interfaz de usuario de cualquier cosa que pueda hacer
no responde

EL ACCESO AL SISTEMA DE ARCHIVO PUEDE SER LENTO A menudo se supone que guardar archivos por escrito
El acceso a la memoria flash en una aplicación móvil es rápido, porque el hardware involucrado es
Bastante rápido Aunque esto es generalmente cierto, la memoria flash tiene un sistema de archivos
Además de eso, puede que no sea el mejor para manejar la concurrencia. Si está ocupado por-
formando una operación de archivo grande, como guardar una actualización descargada, su rápido
el acceso al disco puede esperar un poco antes de ejecutarse, lo que hace que el guardado tarde más
Ger de lo esperado.

En los flujos de usuarios, puede hacer cualquier cosa que implique la interfaz de usuario en el subproceso de interfaz de usuario y cualquier
Lo que implica el almacenamiento en un hilo de fondo. A pesar de que el cálculo para
Incrementar un contador es rápido, todavía tenemos que pensar en hacerlo en un segundo plano.
hilo porque el resultado del cálculo deberá almacenarse. La figura 6.18 muestra
cómo se manejaría el incremento de un contador a través del hilo de la interfaz de usuario y un back-
hilo de tierra.

El contador es
Incrementos de usuario
Subproceso de interfaz de usuario actualizado en
un contador
la interfaz de usuario

El contador es
Antecedentes
incrementado
hilo
y almacenado

Figura 6.18 La aplicación Countr necesita acceder al almacenamiento, por lo que es mejor hacerlo en
un subproceso de fondo antes de volver al subproceso de la interfaz de usuario para mostrar los resultados.

6.3.3 Asignación de código a capas e hilos


Hemos visto cómo asignar flujos de usuarios en capas y subprocesos MVVM, y esta es una
es un buen ejercicio para comenzar a desarrollar aplicaciones móviles multiplataforma. Higo-
ure 6.19 muestra un diseño que puede usar para ayudar a mapear los flujos y el código de sus usuarios. Imprimir o
fotocopie algunas copias o tome la versión SVG del repositorio Git de este libro para usar
con su herramienta de dibujo favorita si desea ahorrar papel.
Debería comenzar pensando en las distintas acciones que su usuario desearía realizar.
forma con su aplicación, como hemos discutido. Luego sepárelos en pasos separados:
qué haría un usuario paso a paso y qué haría la aplicación paso a paso. Dibujar estos
fluye en el diagrama, pensando en qué capa debe ir cada uno (interacción de interfaz de usuario)
las opciones van a la capa de vista con el modelo de vista correspondiente y los pasos que toma la aplicación

Página 200
170 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

Figura
Modelo V V
iew Modelo iew
6.19

https://translate.googleusercontent.com/translate_f 127/131
23/2/2020 Jim Bennett
A
ayuda

trabajo
Hilo de fondo Subproceso de interfaz deHilo
usuario
de fondo Subproceso de interfaz deSubproceso
usuario de interfaz de usuario
fuera

cuales

capa

o
hilo

a
utilizar,

tratar
cartografía

tu

usuario

fluye

en
esta

diagrama.

201
Creando las soluciones 171

internamente ir en la capa del modelo. A medida que coloca las cosas en el modelo de vista y en el diseño del modelo
ers, piense en el subproceso, si deben estar en el subproceso de la interfaz de usuario o en un fondo
¿hilo? Los pasos que necesitan recursos externos o que son lentos siempre pasan a un segundo plano.
hilo.
Intente mapear nuestras dos aplicaciones de ejemplo usando este diagrama y los flujos
definido anteriormente (consulte el apéndice A para ver cómo lo hice). Entonces piensa en el tuyo
ideas de aplicaciones e intente mapearlas. Si ha usado MVVM anteriormente y ha creado una interfaz de usuario
aplicaciones, es posible que ya pienses en estas capas y subprocesos automáticamente
cally, por lo que no necesita usar este diagrama. Pero si todo esto es nuevo para usted, es una buena referencia.
Punto de referencia.
Ahora que hemos pensado cómo poner el código en las capas correctas y
hilos, estamos listos para crear nuestras soluciones. Es hora de encender Visual Studio en tu
plataforma de elección y prepárate para codificar!

6.4 Creando las soluciones


Una vez que haya creado una arquitectura de aplicación aproximada basada en el tipo de clases que desee,
qué capa representan esas clases y en qué hilo debe ejecutarse su código, es hora
para encender su IDE y crear las soluciones reales. En el resto de este capítulo, estamos
vamos a crear soluciones muy parecidas a como creamos el ejemplo Hello Cross-Platform World
en capítulos anteriores Luego veremos algunos conceptos nuevos que son importantes en
desarrollo de aplicaciones móviles: archivos de propiedades de aplicaciones, versiones de SDK y enlaces.
Todo en el resto de este capítulo es relevante para SquareRt y
Countr, y en los próximos capítulos comenzaremos a escribir el código para activar el nuevo
soluciones en aplicaciones totalmente funcionales. Simplemente crearemos la solución para SquareRt
aquí, pero todo lo que discutiremos es relevante para ambas aplicaciones, así que repita el proceso para
Contraataque cuando haya terminado con SquareRt.
Lo primero que debe hacer es crear una nueva solución. Usaremos el mismo material visual
extensión de dio que usamos en el capítulo 2 y creando el mismo tipo de proyecto. Nombra tu
proyecto SquareRt (o invente su propio nombre, por supuesto). En Visual Studio para
Mac, cree una aplicación nativa de una sola página MvvmCross desde la sección Otro> .NET
ción En Windows, elija MvvmCross Single Page Native Application en Visual
C #> MvvmCross y elimine los proyectos de Universal Windows y WPF.
Ahora que tiene su solución, echemos un vistazo a algunas de las formas en que

https://translate.googleusercontent.com/translate_f 128/131
23/2/2020 Jim Bennett
Los objetos en esta solución diferirán de lo que ha visto antes en proyectos de C #, como
aplicaciones web de escritorio o ASP.NET. Las aplicaciones móviles son diferentes de otras aplicaciones C #
cationes: se ejecutan en dispositivos con hardware limitado y con un sistema operativo que cambia los borradores
matemáticamente todos los años. Esto significa que sus aplicaciones deben conocer muy bien la versión del sistema operativo
y qué API están disponibles, además de ser lo más pequeñas posible. También exponen un todo
Una serie de propiedades para el SO y las tiendas de aplicaciones a través de un archivo en el paquete de aplicaciones que proporciona
información sobre tu aplicación. Comencemos mirando cómo se establecen estas propiedades de la aplicación.

Página 202
172 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

6.5 Propiedades de la aplicación


Cuando crea y envía su aplicación móvil, debe agrupar cierta información
dentro de tu aplicación. Esto es utilizado tanto por la tienda de aplicaciones relevante como por el sistema operativo para obtener información.
información sobre su aplicación, como su nombre, icono, versión de sistema operativo compatible y versión de la aplicación
número. Tanto iOS como Android envían un archivo XML que contiene esta información.
Aquí veremos algunas de estas propiedades, pero no el ícono de la aplicación. Móvil
las aplicaciones deben ejecutarse en dispositivos de todas las formas y tamaños, por lo que existen algunas complicaciones
cuando se trata de imágenes, y las veremos para Android en el capítulo 9 y iOS en
Capítulo 11.

6.5.1 Manifiesto de Android


El archivo AndroidManifest.xml en la carpeta Propiedades de la solución se envía con
su paquete de aplicaciones y proporciona información sobre su aplicación a Google Play Store
y el sistema operativo Android. Esto incluye a qué versión de SDK está apuntando (más sobre esto
más adelante en el capítulo), qué permisos necesita su aplicación, el nombre de la aplicación, su versión,
Identificación e icono. En una aplicación nativa de Android Java creada con Android Studio de
Google, el manifiesto también contendrá información sobre las clases que componen
tu aplicación
Afortunadamente, como desarrolladores de Xamarin, no debemos preocuparnos por agregar explícitamente esto
información al archivo XML manifiesto. En cambio, marcamos las clases relevantes con atributos
butes, y estos se agregan automáticamente a la copia del archivo de manifiesto que está empaquetado
envejecido dentro de la aplicación compilada en tiempo de compilación. De nuevo, esto será cubierto en
capítulo 9, pero es posible que ya haya visto esto en la actividad FirstView en First-
Archivo View.cs en la carpeta Vistas de la aplicación de Android: esta clase se marcó con un
Atributo de actividad ( [Activity (Label = "...")] ), que indica que en el momento de la compilación
debe agregarse al manifiesto como una actividad con una etiqueta particular.
Aunque este es un archivo XML, realmente no hay necesidad de editar manualmente el XML.
Visual Studio viene con un editor para esto: puede acceder a él en Visual Studio para Mac
desde el cuadro de diálogo Opciones de proyecto o haciendo doble clic en el archivo AndroidManifest.xml en
la carpeta Propiedades (figura 6.20); en Windows puedes acceder desde el proyecto
Ficha Propiedades (haga clic con el botón derecho en la aplicación y seleccione Propiedades). Si lo abres por doble
Al hacer clic en el archivo en la Solución Pad en Visual Studio para Mac, se abre en una pestaña con dos
subpestañas: una para editar el archivo con el mismo editor que el cuadro de diálogo Opciones de proyecto, y
el otro muestra el XML sin procesar (figura 6.20). En Visual Studio, haciendo doble clic en
El archivo en el Explorador de soluciones abre una pestaña con solo el XML sin procesar.
Hay varios artículos de interés para nosotros ahora:
▪ Nombre de la aplicación
▪ Nombre del paquete
▪ Número de versión
▪ Nombre de la versión
▪ Permisos requeridos

203 de 1189.
Propiedades de la aplicación 173

El archivo AndroidManifest.xml vive en la carpeta Propiedades.

https://translate.googleusercontent.com/translate_f 129/131
23/2/2020 Jim Bennett

Figura 6.20 El archivo del Manifiesto de Android en la Solución Pad y en el editor

Un OLICITUD NOMBRE
El nombre de la aplicación es el nombre de su aplicación tanto en Google Play Store
y en tu dispositivo. Notarás en la figura 6.20 que está configurado en @ string / Application-
Nombre , que es una referencia de recursos. Los verás mucho en las aplicaciones de Android, más bien
que codificar un valor, hace referencia a un recurso. Estos recursos están en el
Carpeta de recursos, que contiene una subcarpeta llamada valores que contienen un archivo XML,
string.xml. Si abre este archivo, verá lo siguiente.

El listado 6.1 strings.xml contiene cadenas que se pueden usar en cualquier lugar de su aplicación

<? xml version = "1.0" encoding = "utf-8"?>


<recursos> El nombre de la versión
<string name = "VersionName"> 1.0 </string> de la aplicación
<string name = "ApplicationName"> SquareRt </string>
El nombre de
</resources>
solicitud

Si desea cambiar el nombre de la aplicación, puede editar el valor de ApplicationName en este


XML, y la aplicación cambiará de nombre automáticamente la próxima vez que compile.

204 de 1189.
174 C APÍTULO 6 Diseñando aplicaciones multiplataforma MVVM

Cubriremos estos más en el capítulo 9, pero la razón principal para usar archivos de recursos
para almacenar valores es para que pueda localizar su aplicación fácilmente. En este ejemplo solo nosotros
tiene un archivo strings.xml, pero puede tener múltiples recursos en función de la configuración regional de
el usuario de la aplicación: un archivo para usuarios de inglés de EE. UU., uno para usuarios chinos y otro para francés
usuarios, y así sucesivamente. Al contener todas sus cadenas en un archivo, es fácil obtener su aplicación
traducido: solo hay un archivo XML para traducir. La localización está fuera del alcance de
este libro, pero puede encontrar más información en "Localización con
Recursos "Guía de la API: http://mng.bz/fb7Y .

P NOMBRE DE ACKAGE
El nombre del paquete es el nombre único para su paquete de aplicación, y se utiliza para
identifica tu aplicación en Google Play Store. Cuando desee enviar actualizaciones de aplicaciones a
En la tienda, este nombre de paquete identifica qué aplicación se está actualizando. La forma normal
para este nombre es utilizar su empresa o nombre de dominio personal invertido, con el sufijo
Un identificador para su aplicación. Por ejemplo, si estuviera creando esta aplicación para publicación,
Tendría un nombre de paquete de io.jimbobbennett.squarert . Una vez que su aplicación ha sido
publicado en la tienda, no puede cambiar este valor, o Play store pensará que está
publicar una aplicación diferente.
A diferencia del nombre de la aplicación, no es necesario definirlo en el archivo strings.xml
porque esto nunca cambiará para coincidir con un entorno local. Una vez que se establece este nombre y su aplicación es
publicado, no puede cambiarlo, así que asegúrese de configurarlo correctamente antes de publicarlo.
V NÚMERO DE ERSIÓN
Este es el número de versión de su paquete (también conocido en XML como el ver-
código sion). Este número es utilizado por Google Play Store y el dispositivo para rastrear
actualizaciones: si el paquete en la tienda tiene un número de versión más alto que el que está en
El dispositivo, la aplicación se puede actualizar. Solo puede enviar a la tienda un paquete actualizado.
edad con un número de versión más alto que el que ya está en la tienda, no tiene que
ser 1 más alto, puedes incrementarlo por lo que quieras, solo necesita ser
mayor.
Hay un límite en este número, es un límite grande (2,100,000,000 para ser exactos), pero
se puede llegar fácilmente si utiliza herramientas de compilación automatizadas que incrementan este número o
configúrelo en valores basados en la hora actual o el número de revisión del código fuente. Una vez que es
alcanzado, ya no puede actualizar su aplicación, así que tenga cuidado con grandes números.
V NOMBRE DE ERSIÓN
Este es el nombre de su versión interna para su aplicación, y es una cadena que se puede establecer en
manifiesto o en el archivo de recursos string.xml, como se muestra anteriormente en el listado 6.1. Más desarrollado
Los operadores utilizan una versión de varias partes para que puedan realizar un seguimiento interno de las versiones. Puedes configurar esto
a lo que sea relevante para ti.
R PERMISOS EQUIPADOS
Cuando está creando aplicaciones móviles, puede integrar su aplicación estrechamente con la función

https://translate.googleusercontent.com/translate_f 130/131
23/2/2020 Jim Bennett
tures del dispositivo, así como con otras aplicaciones que vienen integradas en el sistema operativo, como un
cámara, contactos y calendarios. Obviamente, hay problemas de privacidad con esto: usted

https://translate.googleusercontent.com/translate_f 131/131

También podría gustarte