web-dev-qa-db-fra.com

Quand effacer le répertoire de cache sous Android?

J'ai une application qui affiche des images sur Internet (vitrine pour le travail de designer). Je commence la mise en cache de mon contenu dans le répertoire de cache interne, mais le contenu de l'application peut prendre environ 150 Mo en taille de cache. Et ce que Android docs dit:

Vous devez toujours conserver vous-même les fichiers de cache et rester dans une limite raisonnable d'espace utilisé, telle que 1 Mo. Lorsque l'utilisateur désinstalle votre application, ces fichiers sont supprimés.

J'ai donc jeté un coup d'œil à l'application Currents (Galaxy Nexus) et la taille du cache pour l'application est de 110 Mo. Mais ce qui est étrange, c’est que des applications telles que Google Currents et Google Maps mettent en cache le contenu dans un fichier appelé (Données de stockage USB):

enter image description here

Alors, quelle est cette "données de stockage USB" que l'application précédente utilise. Et si vous implémentez la mise en cache dans votre application, effectuez-vous une boucle sur tous les vos fichiers d’application en cache pour obtenir la taille à chaque fois que vous devez insérer quelque chose, puis le comparer et l’effacer? Ou maintenez-vous la mise en cache du contenu jusqu'à ce que Android décide de son heure pour nettoyer un répertoire de cache d'application?

Je suis vraiment intéressé de savoir quel est le flux de gestion du cache dans Android, ou du moins ce que font les autres applications avec un contenu volumineux à mettre en cache.

76
Jimmy

Avant d’arriver à votre question, voici une brève explication des deux types de stockage:

Cache

Ceci est un répertoire spécifique à l'application sur le système de fichiers. L'intention de ce répertoire est de stocker des données temporaires que votre application devra peut-être conserver entre les sessions, mais ne sera peut-être pas indispensable pour les conserver indéfiniment. Vous accédez généralement à ce répertoire avec Context.getCacheDir() . Cela apparaîtra comme "Cache" dans les paramètres de votre application.

Des dossiers

Comme le répertoire de cache, votre application possède également un répertoire spécifique à l’application pour contenir des fichiers. Les fichiers de ce répertoire existeront jusqu'à ce que l'application les supprime explicitement ou que l'application soit désinstallée. Vous accédez généralement à ce répertoire avec Context.getFilesDir() . Cela peut apparaître sous différentes formes sur l'écran d'informations de l'application, mais dans la capture d'écran, il s'agit de "Données de stockage USB".

REMARQUE: Si vous souhaitez explicitement placer sur un support externe (généralement une carte SD), vous pouvez utiliser Context.getExternalFilesDir(String type) .

La différence

Les deux répertoires ne sont spécifiques qu'à votre application (les autres applications n'ont pas accès). Une des différences entre le répertoire de cache et le répertoire de fichiers réside dans le fait que si le système manque de stockage, le premier endroit où il libérera des ressources se trouve dans votre répertoire de cache. Le système n'effacera aucune donnée du répertoire de fichiers. Une autre différence est que le répertoire de cache peut généralement être effacé manuellement à partir de l'écran d'informations sur l'application. Le répertoire de fichiers le peut généralement aussi, mais effacer le répertoire de fichiers effacera également le répertoire de cache.

Lequel dois-je utiliser?

Cela dépend de la pertinence de ces données par rapport à la durée de vie de votre application. Si vous n’avez besoin que de données pour une session et que vous ne savez pas si vous aurez besoin de les utiliser à nouveau, n’utilisez pas non plus. Il suffit de le garder en mémoire jusqu'à ce que vous n'en ayez plus besoin. Si vous pensez que vous devrez réutiliser les données entre plusieurs sessions, mais que vous n'avez pas eu pour conserver une copie papier, utilisez le répertoire de cache. Si vous devez absolument avoir ces données, ou s'il s'agit de données volumineuses nécessitant un stockage persistant, utilisez le répertoire files. Voici quelques exemples auxquels je peux penser:

  • Cache - Un email récemment ouvert
    • Une fois ouvert, mettez les données en cache afin que, lorsque l'utilisateur souhaite relire cet e-mail, il se charge instantanément plutôt que d'utiliser à nouveau le réseau pour récupérer les mêmes données. Je n'ai pas besoin de garder cela pour toujours, parce que l'utilisateur finira par avoir fini avec le courrier électronique.
  • Fichiers - Une pièce jointe téléchargée depuis un courrier électronique
    • Ceci est une action de l'utilisateur qui dit "Je veux conserver ces données afin de pouvoir les récupérer à tout moment." Par conséquent, placez-le dans le répertoire files car je ne souhaite jamais supprimer ce fichier tant que l'utilisateur ne le souhaite pas.

Quand devrais-je effacer le répertoire de cache?

De la Context.getCacheDir() javadocs:

Remarque: vous ne devez pas compter sur le système pour supprimer ces fichiers pour vous. vous devez toujours avoir un maximum raisonnable, tel que 1 Mo, pour la quantité d'espace que vous utilisez avec les fichiers en cache, et effacer ces fichiers lorsque vous dépassez cet espace.

Il utilise l'exemple de 1 Mo, mais cela peut être raisonnable ou non pour votre application. Quoi qu'il en soit, vous devez définir un maximum strict. La raison en est simplement de concevoir une application responsable. Alors, quand devriez-vous vérifier? Je recommanderais de vérifier chaque fois que vous voulez mettre quelque chose dans le répertoire de cache. Voici un gestionnaire de cache très simple:

public class CacheManager {

    private static final long MAX_SIZE = 5242880L; // 5MB

    private CacheManager() {

    }

    public static void cacheData(Context context, byte[] data, String name) throws IOException {

        File cacheDir = context.getCacheDir();
        long size = getDirSize(cacheDir);
        long newSize = data.length + size;

        if (newSize > MAX_SIZE) {
            cleanDir(cacheDir, newSize - MAX_SIZE);
        }

        File file = new File(cacheDir, name);
        FileOutputStream os = new FileOutputStream(file);
        try {
            os.write(data);
        }
        finally {
            os.flush();
            os.close();
        }
    }

    public static byte[] retrieveData(Context context, String name) throws IOException {

        File cacheDir = context.getCacheDir();
        File file = new File(cacheDir, name);

        if (!file.exists()) {
            // Data doesn't exist
            return null;
        }

        byte[] data = new byte[(int) file.length()];
        FileInputStream is = new FileInputStream(file);
        try {
            is.read(data);
        }
        finally {
            is.close();
        }

        return data;
    }

    private static void cleanDir(File dir, long bytes) {

        long bytesDeleted = 0;
        File[] files = dir.listFiles();

        for (File file : files) {
            bytesDeleted += file.length();
            file.delete();

            if (bytesDeleted >= bytes) {
                break;
            }
        }
    }

    private static long getDirSize(File dir) {

        long size = 0;
        File[] files = dir.listFiles();

        for (File file : files) {
            if (file.isFile()) {
                size += file.length();
            }
        }

        return size;
    }
}

Bien sûr, cela pourrait être une opération coûteuse, vous devriez donc planifier la mise en cache sur un thread en arrière-plan.

En outre, cela pourrait être aussi compliqué que nécessaire. Dans mon exemple, je suppose que tous les fichiers en cache sont placés à la racine du répertoire de cache, je ne recherche donc pas de sous-répertoires potentiels. La routine de suppression de fichiers peut également devenir plus sophistiquée, telle que la suppression de fichiers à la date d’accès la plus ancienne.

Une chose à garder à l'esprit lorsque vous décidez de mettre en cache des données est que vous devez toujours prévoir le cas où vos données en cache n'existeraient plus. Ayez toujours une routine en place pour récupérer les données par des moyens externes lorsque votre cache ne les a pas en mémoire. De même, vérifiez toujours votre cache avant de récupérer des données en externe. L'objectif du cache est de réduire l'activité du réseau, les processus longs et de fournir une interface utilisateur réactive dans votre application. Alors utilisez-le de manière responsable :)

189
Jason Robinson

c'est le meilleur moyen d'effacer le cache de l'application lorsque l'activité se termine pour que chaque fois que le cache soit effacé lors de la nouvelle activité.

mettre ce code dans onDestroy () pour effacer le cache de l'application

@Override
protected void onDestroy() {

    super.onDestroy();
    try {
        trimCache(this);
       // Toast.makeText(this,"onDestroy " ,Toast.LENGTH_LONG).show();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public static void trimCache(Context context) {
    try {
       File dir = context.getCacheDir();
       if (dir != null && dir.isDirectory()) {
          deleteDir(dir);
       }
    } catch (Exception e) {
       // TODO: handle exception
    }
 }

public static boolean deleteDir(File dir) {
    if (dir != null && dir.isDirectory()) {
       String[] children = dir.list();
       for (int i = 0; i < children.length; i++) {
          boolean success = deleteDir(new File(dir, children[i]));
          if (!success) {
             return false;
          }
       }
    }
    // The directory is now empty so delete it
    return dir.delete();
}
15
Chirag

Dépend du type d'application:

  • Certaines applications n'utilisent que des sessions uniques et n'ont pas besoin de mémoriser de données. Vous pouvez donc vider le cache à tout moment (certaines applications le font même automatiquement dans leur activité onStop).
  • La plupart des applications conservent vos données car elles mémorisent vos paramètres, le compte que vous avez utilisé pour vous connecter, ... Dans ce cas, il est préférable d'effacer le cache uniquement lorsque vous n'utilisez pas beaucoup l'application.

Également:

So i took a look at Chrome app (Galaxy Nexus) and the cache size for the application is 110 MB. But what wired is that applications like Google current & Google maps cache the content in something called (USB Storage Data) :

D’après les informations dont nous disposons, les données de stockage Usb ont une utilisation différente de celle du cache: le stockage consiste à stocker des informations spécifiques à un programme (telles que des cartes pour une application GPS), le cache étant utilisé pour stocker des informations spécifiques à l’utilisateur (telles que les connexions).

Dans le cas de Google Maps: je suppose qu'ils stockent les données de la carte dans le stockage USB et conservent vos paramètres et l'historique de recherche dans le cache ==> les données de la carte sont spécifiques à l'application, les paramètres et l'historique de recherche sont spécifiques à l'utilisateur

1
Andreas

Je pense que l’idée derrière le cache est d’écrire ce que vous voulez et Android gérera sa taille si elle est trop haute.

N'oubliez pas que vous pouvez écrire des fichiers dans le cache, mais vérifiez toujours si le fichier est toujours enregistré lorsque vous essayez d'y accéder. Et laissez Android gérer le cache.

1
Marcio Covre

Selon la documentation, le système effacera le cache lorsque le stockage interne de l'appareil est faible . Depuis API8, vous avez getExternalCacheDir () la méthode que j’estime utile depuis que je vous ai lu, vous pouvez disposer d’environ 150 Mo de données, mais l’inconvénient du cache externe c’est que vous devrez nettoyer vous-même votre répertoire de cache trop grand.

0
Kowlown