[Windows 10] Novedades XAML: x:DeferLoadStrategy

XAMLIntroducción

Cuando desarrollamos aplicaciones móviles buscamos múltiples objetivos, que sean atractivas visualmente, intuitivas, fluidas, ágiles, etc. Habitualmente se le suele dar mucho peso a nivel funcional e incluso en el aspecto visual pero en ocasiones, se deja la fluidez y agilidad de la App en un segundo plano realizando mejoras en fases finales y en ocasiones como mejoras futuras.

En este aspecto entran en juego herramientas fundamentales para el análisis de rendimiento.  Consumo de CPU, memoria o red donde se suelen apreciar métodos no asíncronos o pesados, la necesidad de cache para reducir consumo de red, etc.

Con herramientas como el Visual Tree Explorer también se puede intuir y detectar casos de interfaz innecesariamente pesada donde los tiempos de carga se elevan más de lo deseado. Hablamos de interfaces complejas. Por ejemplo, vistas con diferentes paneles donde suele estar uno de ellos visible y el resto ocultos o en un segundo plano a la espera de cierta condición.

¿Qué podemos hacer en estos casos?

En este artículo vamos a desgranar el uso de x:DeferLoadStrategy que nos permitirá mejorar situaciones como las descritas anteriormente.

x:DeferLoadStrategy

x:DeferLoadStrategy nos permite retrasar la creación de un elemento y sus elementos hijos lo que reduce los tiempos necesarios para la creación de la UI y por lo tanto de carga. Sin embargo, nada en la vida es gratis. A cambio, incrementamos levemente el consumo de memoria.

NOTA: Cada elemento que retrasamos en su inicialización con x:DeferloadStrategy añade 600 Bytes en el consumo de memoria.

Podemos deducir que a mayor cantidad de elementos que nos ahorremos del árbol visual, en menor tiempo se realizara la inicialización de la vista pero aumentando el consumo de memoria. Por lo tanto, el uso de la etiqueta es recomendado aunque requiere un análisis mínimo.

Crearemos un nuevo proyecto UAP:

Nueva App UAP

Nueva App UAP

Añadimos las carpetas Views, ViewModels y Services además de las clases base necesarias para implementar el patrón MVVM de la misma forma que vimos en este artículo.

Definimos nuestra interfaz:

<StackPanel Margin="12">
     <TextBlock
          Text="x:DefeLoadStrategy"
          FontWeight="Black"/>
     <TextBlock
          Text="x:DeferLoadStrategy nos permite retrasar la creación de un elemento y sus elementos hijos lo que reduce los tiempos necesarios para la creación de la UI y por 

lo tanto de carga. Sin embargo, nada en la vida es gratis. A cambio, incrementamos levemente el consumo de memoria."
          TextWrapping="WrapWholeWords" />
     <Grid>
           <Image
                Stretch="UniformToFill"
                Source="ms-appx:///Assets/NinjaCat.jpg" />
     </Grid>
     <Button
          Content="Realize"
          Command="{Binding RealizeElementsCommand}"/>
</StackPanel>

Vamos a retrasar la creación del Grid que contiene la imagen para crearlo bajo nuestro propio interés al pulsar el botón. El uso es sencillo:

<Grid x:Name="DeferredPanel"  
      x:DeferLoadStrategy="Lazy">
      <Image
           Stretch="UniformToFill"
           Source="ms-appx:///Assets/NinjaCat.jpg" />
</Grid>

Utilizamos la etiqueta x:DeferLoadStrategy=”Lazy” en nuestro Grid. De esta forma indicamos que retrasamos la creación del panel y todo su contenido. Para utilizar la etiqueta debemos:

  • Definir un nombre con x:Name. Para iniciar posteriormente la incialización utilizaremos el nombre.
  • Podemos utilizarlo con cualquier elemento visual derivado de UIElement. No podemos utilizarlo con Page o UserControl.
  • no podremos utilizar con XAML XamlReader.Load.

Definimos en la ViewModel de la vista el comando a ejecutar cuando pulsemos el botón:

private ICommand _realizeElementsCommand;

public ICommand RealizeElementsCommand
{
     get { return _realizeElementsCommand = _realizeElementsCommand ?? new DelegateCommand(RealizeElementsCommandExecute); }
}

private void RealizeElementsCommandExecute()
{

}

Nos centramos ahora en el código que se ejecutará en la ejecución del comando. Tenemos varias formas de crear el elemento que hemos retrasado:

var frame = (Frame)Window.Current.Content;
var page = (Page)frame.Content;

page.FindName("DeferredPanel");

La forma más habitual será utilizar el método FindName pasándole el nombre del elemento. Otras formas disponibles son:

  • Utilizar una propiedad del elemento retrasado en un Setter o StoryBoard de un VisualState.
  • Utilizar el elemento retrasado en una animación.
  • Utilizando el método GetTemplateChild pasándole el nombre del elemento.

Si ejecutamos la App veremos:

Antes de crear el Grid con imagen

Al pulsar el botón:

Tras crear Grid

El panel que retrasamos se crea. En este momento:

  • Se lanza el evento Loaded del panel.
  • Se evalúan los Bindings establecidos en el elemento.

Podéis descargar el ejemplo completo realizado a continuación:

También tenéis el código fuente disponible e GitHub:

Ver GitHub

Recordar que podéis dejar en los comentarios cualquier tipo de sugerencia o pregunta.

Más información

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s