[Windows 10] Novedades XAML: x:DeferLoadStrategy

Introducció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

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *