何时清除Android中的caching目录?

我有一个应用程序,显示从互联网上的图片(展示devise师的工作)。 我开始在内部caching目录中caching我的内容,但是应用内容可能需要大约150 MB的caching大小。 什么安卓文档说:

您应该始终自行维护caching文件,并保持在合理的占用空间(如1MB)范围内。 当用户卸载您的应用程序时,这些文件被删除。

所以我看了一下Currents应用程序(Galaxy Nexus),应用程序的caching大小为110 MB。 但奇怪的是,像Google Currents&Google Maps这样的应用程序将这些内容caching在一个名为(USB存储数据)的东西里:

在这里输入图像描述

那么以前的应用程序使用的是什么“USB存储数据”。 如果你在你的应用程序中实现caching,你是否将caching中的所有应用程序文件循环,以便每次需要插入内容时都能获得大小,然后进行比较和清除? 或者,您是否继续caching内容,直到Android决定清理某个应用程序caching目录为止?

我真的很想知道在Android中pipe理caching的stream程是什么,或者至less有什么其他应用程序用大内容来caching。

在解决您的问题之前,请先简单介绍两种存储types:

高速caching

这是文件系统上的特定于应用程序的目录。 这个目录的意图是存储临时数据,你的应用程序可能需要在会话之间保持一段时间,但是永远保留它们可能并不重要。 您通常使用Context.getCacheDir()访问此目录。 这将显示为您的应用程序设置“caching”。

与caching目录一样,您的应用程序也有一个用于保存文件的特定于应用程序的目录。 此目录中的文件将一直存在,直到应用程序显式删除它们或卸载该应用程序为止。 您通常使用Context.getFilesDir()访问此目录。 这可以显示在应用程序信息屏幕上的各种东西,但在你的屏幕截图这是“USB存储数据”。

注意:如果你想明确地放置在外部媒体上(通常是SD卡),你可以使用Context.getExternalFilesDir(String type)

区别

这两个目录都只针对您的应用程序(其他应用程序无权访问)。 高速caching和文件目录之间的差异之一是,如果系统的存储空间不足,首先要释放资源的地方是来自高速caching目录。 系统不会清除文件目录中的任何数据。 另一个区别是,通常可以从应用程序信息屏幕手动清除caching目录。 文件目录通常也可以,但清除文件目录也将清除caching目录。

我使用哪一个?

这取决于数据与应用程序的生命周期的重要性。 如果您只需要一个会话的数据,并且您怀疑需要再次使用该数据,则不要使用这两个数据。 只要保存在内存中,直到你不需要它。 如果您怀疑需要在多个会话之间重复使用数据,但不必保留硬拷贝,请使用caching目录。 如果您必须拥有这些数据,或者数据量非常大,需要持久存储,请使用文件目录。 以下是我能想到的一些例子:

  • caching – 最近打开的电子邮件
    • 一旦打开,caching数据,所以当用户想要再次读取该电子邮件时,它立即加载,而不是再次使用networking来检索相同的数据。 我不需要永远保持这一点,因为最终用户将完成电子邮件。
  • 文件 – 从电子邮件下载的附件
    • 这是用户的一个操作,他说:“我想保留这些数据,这样我就可以在需要的时候将其恢复。” 因此,把它放在文件目录中,因为我不想删除这个文件,直到用户想删除它。

什么时候应该清除caching目录?

Context.getCacheDir() javadocs:

注意:你不应该依赖系统为你删除这些文件; 对于caching文件占用的空间量,应始终具有合理的最大值(如1 MB),并在超过该空间时修剪这些文件。

它使用1 MB的例子,但这可能会或可能不适合您的应用程序。 无论如何,你需要设定一个最大值。 原因是简单归结为devise一个负责任的应用程序。 那么你应该什么时候检查? 我会build议检查每一次你想把东西放在caching目录。 这是一个非常简单的cachingpipe理器:

 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; } } 

当然,这可能是一个昂贵的操作,所以你应该计划在后台线程caching。

而且,这可能会像你需要的那样复杂。 在我的例子中,我假设所有的caching文件都放在caching目录的根目录下,所以我不检查潜在的子目录。 用于删除文件的例程也可以变得更复杂,例如按最早的访问date删除文件。

在决定caching数据时要牢记的一点是,您需要始终计划caching数据不再存在的情况。 当你的caching没有存储时,总是要有一个例行程序来通过外部方式检索数据。 同样,在外部检索数据之前总是检查caching。 caching的目的是减lessnetworking活动,长时间的stream程,并在您的应用程序中提供响应式用户界面。 因此,负责任地使用它:)

我最好的方式来清理应用程序caching时,活动完成,以便每次caching清除时,新的活动调用。

把这个代码放在onDestroy()中,以清除应用程序caching

 @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(); } 

我认为caching背后的想法是写任何你想要的,如果它太高,Android会pipe理它的大小。

您应该记住,您可以将文件写入caching,但始终会在尝试访问文件时检查文件是否仍保存。 让androidpipe理caching。

取决于应用程序的types:

  • 某些应用程序只使用单个会话,不需要记住任何数据,因此您可以在需要时清除caching(有些应用程序甚至可以在o​​nStop活动中自动执行此操作)
  • 大多数应用程序会保存数据,因为它们记住了您的设置,您用来login的帐户……在这种情况下,最好只在您不使用应用程序时清除caching。

也:

 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) : 

AFAIK,Usb存储数据与caching有不同的用处:存储是stored procedures特定的信息(如GPS应用程序的地图),caching用于存储用户特定的信息(如login)

谷歌地图的情况下:我假设他们存储地图数据在USB存储,并保持您的设置和search历史logging在caching==>地图数据是应用程序特定的,设置和search历史是用户特定的

根据文档,系统将在内部存储器设备较低时清除caching。 由于API8你有getExternalCacheDir()方法,我认为有用的,因为我读你可以有大约150MB的数据,但外部caching的缺点是你将不得不自己清理caching目录,如果它太大了。