Skip to content
Aprende Angular de forma rápida y efectiva  Ver curso

Ionic Framework: cache y refresco de vistas

Una característica muy potente, pero que a la vez genera algo de confusión del framework ionic, es la caché automática de vistas. Hoy veremos como recargar vistas cacheadas, y la diferencia entre usar caché o no usarla.

¿Quieres aprender Ionic Framework? ¡¡Mira mi curso de ionic completamente gratuito!!

Caché de ion-view

Ionic cachea por defecto las vistas ion view para mejorar el rendimiento de la navegación. Cuando salimos de una vista, ésta se mantiene en el DOM, pero se desconecta su scope del ciclo $watch. Al volver a esa vista, se reconecta su scope, y su elemento del DOM se vuelve la vista activa, manteniendo por ejemplo la posición de scroll.

Este mecanismo permite a la vista cargar más rápido, ya que no tiene que reconstruir el DOM (la vista y todo su contenido ya está creada), ni crear de nuevo el scope, pero también implica que el controlador de la vista cacheada no se vuelve a crear, ya está cargado.

¿En qué afecta navegar a una vista cacheada?

Como hemos dicho:
* Agiliza la navegación
* NO recarga el controlador

Si desarrollas un controlador sin tener en cuenta la caché, es probable que incluyas en su constructor algunas líneas de código que quieres que se ejecuten cada vez que se recarga la vista, PERO SOLO SE LLAMARÁN UNA VEZ.

¿Cómo ejecutar código cada vez que se llama una vista cacheada?

Para solucionar este problema, la directiva ion-view incluye ciertos eventos relacionados con su ciclo de vida.

De estos eventos, el más habitual es el de beforeEnter, que se ejecuta cada vez que se la vista pasa a ser la vista activa. Para ejecutar código cada vez que llamamos a una vista cacheada, haríamos:

.controller('MyCachedViewCtrl', function($scope){

    //...some stuff...

    $scope.$on('$ionicView.beforeEnter', function(){
        //[your code HERE]
    });
});

¿Cómo navegar a una vista cacheada y refrescarla?

Más allá de los eventos del ciclo de vida de ion-view, puede ser que de forma puntual necesites navegar a una vista y recargarla entera, en lugar de utlizar la versión cacheada. Para esto tenemos el método clearCache del servicio $ionicHistory.

$ionicHistory.clearCache() elimina todas las vistas de caché y devuelve una promise al completar el proceso, por lo que si queremos limpiar la caché e ir a una vista concreta, deberíamos hacerlo del siguiente modo:

$ionicHistory.clearCache().then(function(){ $state.go('firstState');});

¿Cómo refrescar la propia vista si está cacheada?

Para recargar una vista, podemos llamar al método $state.reload.

No obstante, el método $ionicHistory.clearCache() que acabamos de ver elimina el resto de vistas de la cache, pero la propia vista sigue cacheada. Esto impide que podamos hacer un refresh completo de nuestra vista sin salir de ella.

La única solución que podemos aplicar aquí, es utilizar los eventos de ciclo de vida de la vista como $ionicView.beforeEnter que ya hemos comentado. Para hacerlo más sencillo, podemos concentrar la inicialización de la vista en un método, y llamarlo de nuevo con el evento.

.controller('MyCachedViewCtrl', function($scope){
    var initView = function(){...};
    //...some stuff...

    $scope.$on('$ionicView.beforeEnter', function(){
        initView();
    });

    $scope.refresh = function(){
        $state.reload(true);
    };
});

¿Cómo desabilitar la cache de una vista?

Si no queremos que una vista esté cacheada, ya sea por que su contenido siempre va a cambiar, por que puede añadir una complejidad extrema a nuestro DOM, o por cualquier otra razón, podemos hacerlo desde el propio template con la directiva view-cached=”false”.

¿Qué pasa con la cache cuando navego hacia atrás?

Por defecto, cuando volvemos de una vista, ionic elimina la misma de la cache. Tiene lógica desde el punto de vista de que es más probable que queramos navegar a una vista de la que venimos (hacer “atrás”) y por tanto tenerla en caché, pero que una vez hemos salido de ella, es más improbable que queramos volver a entrar.

Esto se puede configurar, de todos modos mediante el provider $ionicConfigProvider:

$ionicConfigProvider.views.forwardCache(true);

Ejemplos prácticos

Si quieres ver de primera mano las diferencias entre vistas cacheadas y no cacheadas, recargas de vista, etc. lo mejor es que juegues un poco con el siguiente codepen, y mires un rato el código.

See the Pen Ionic cache-view and refresh view example by Enrique (@-kaik-) on CodePen.

Published inAngularJSHybrid appIonic Framework

5 Comments

  1. Daniel Osorio Daniel Osorio

    Excelente!

  2. Juan Carlos Juan Carlos

    Hola, enhorabuena por el blog, me ha ayudado mucho a crear mi aplicación, pero tengo un problema.

    Tengo una aplicación por tabs, en uno de ellos hay una serie de botones y en otro tab está el registro de las pulsaciones de los botones, entre otros datos almacena en una factoría el nombre y la fecha, de la pulsación.

    En la vista de registro muestro una ion list, a partir de esa lista, ordenada por fecha descendente y con el cache desactivado, pero la ultima pulsación siempre se coloca debajo de todas (cuando debería ir la primera), he probando con el cacheClear al cambiar de vista y también al eliminar un elemento de la lista, pero la única forma de que se ordene de manera correcta es reiniciando la aplicación.

    Espero que tengas una idea de donde podría estar el error o si puedo forzar el reinicio, porque la factoria si que tiene los elementos bien almacenados.

    • Enrique Oriol Enrique Oriol

      ¡Gracias!

      En cuanto a tu problema, no sé qué decirte, tendrás que explorar en detalle el código. Te sugiero que empieces por llamar al filtro de ordenación desde código en lugar de hacerlo en el template para comprobar ahí cuando se llama y su salida.

      • Juan Carlos Juan Carlos

        Gracias por contestar tan rápido, he cambiado la ordenación para que funcionase por nombre y va bien y despues he probado con $hashkey y funciona exactamente como quiero (por fecha de introducción).

        Después de esto me he dado cuenta que cuando guardo el valor de actual date, la guarda en este formato «Wed Sep 28 2016 08:49:32 GMT+0200 (Hora de verano romance)» y cuando la muestro (filtrada por mi) tiene este «2016-09-28T06:31:14.623Z». Creo que esto es lo que me está dando fallos.

        Será porque obtengo la fecha actual con new date()?

        Un saludo.

      • Juan Carlos Juan Carlos

        Al final parte de la culpa lo tiene el track by $index y la manera de obtener la fecha, con esta linea lo soluciono: $scope.newActv.date = $filter(‘date’)(new Date(), «short»);

Deja un comentario