您的位置:首页 > 运维架构

Google提供给Android Developer的缓存策略

2016-11-07 14:40 246 查看

注:Android野生Coder一名,文章来源:https://developer.android.com/training/basics/data-storage/files.html#WriteExternalStorage

一、数据的存储 

      所有
Android 设备都有两个文件存储区域:“内部”和“外部”存储。这些名称在 Android 早期产生,当时大多数设备都提供内置的非易失性内存(内部存储),以及移动存储介质,比如微型 SD 卡(外部存储)。一些设备将永久性存储空间划分为“内部”和“外部”分区,即便没有移动存储介质,也始终有两个存储空间,并且无论外部存储设备是否可移动,API 的行为均一致。以下列表汇总了关于各个存储空间的实际信息。
   (一)内部存储: 
      


它始终可用。

只有您的应用可以访问此处保存的文件。

当用户卸载您的应用时,系统会从内部存储中移除您的应用的所有文件。

当您希望确保用户或其他应用均无法访问您的文件时,内部存储是最佳选择 
      

         getCacheDir()方法用于获取/data/data/<application
package>/cache目录

       
 getFilesDir()方法用于获取/data/data/<application package>/files目录

    A:先看files目录

          a.

String FILE_NAME = "temp.log";

String data = "Hello World !";

try {

FileOutputStream outputStream = openFileOutput(FILE_NAME, Context.MODE_PRIVATE);

outputStream.write(data.getBytes());

outputStream.close();

} catch (Exception e) {

e.printStackTrace();

}


          b.该目录下多出来我们定义的temp.log文件





        最后把文件拉出来确定下数据就是我们写入的“Hello World” 。
B:再看cache目录
       a:定义方法

//以下方法从 
URL
 提取文件名并在您的应用的内部缓存目录中以该名称创建文件:
public File getTempFile(Context context, String url) {

File file = null;

try {

String fileName = Uri.parse(url).getLastPathSegment();

file = File.createTempFile(fileName, null, context.getCacheDir());

} catch (IOException e) {

e.printStackTrace();

}

return file;

}


       b.相同操作,更换一下路径

String FILE_NAME = "temp.log";

String data = "Hello World !";

try {

//          FileOutputStream outputStream = openFileOutput(FILE_NAME, Context.MODE_PRIVATE);

FileOutputStream outputStream = new FileOutputStream(getTempFile(this, getCacheDir().getAbsolutePath()));

outputStream.write(data.getBytes());

outputStream.close();

} catch (Exception e) {

e.printStackTrace();

}


      c.然后看结果



看到cache目录下多出来一个cache2093102610.tmp文件,这就是系统提供的一种存储命名方式了。牵出来vi下:结果一样的。(打开方式要选择)

   (二)外部存储:

它并非始终可用,因为用户可采用 USB 存储设备的形式装载外部存储,并在某些情况下会从设备中将其移除。
它是全局可读的,因此此处保存的文件可能不受您控制地被读取。
当用户卸载您的应用时,只有在您通过
getExternalFilesDir()
 将您的应用的文件保存在目录中时,系统才会从此处移除您的应用的文件。
对于无需访问限制以及您希望与其他应用共享或允许用户使用计算机访问的文件,外部存储是最佳位置。

  
    提示:尽管应用默认安装在内部存储中,但您可在您的清单文件中指定 
android:installLocation
 属性,这样您的应用便可安装在在外部存储中。当
APK 非常大且它们的外部存储空间大于内部存储时,用户更青睐这个选择。 

    可以看到installLocation有三个选项。基本见名知义,详情请考https://developer.android.com/guide/topics/data/install-location.html
    由于外部存储可能不可用—比如,当用户已将存储挂载到电脑或已移除提供外部存储的 SD 卡时—因此,在访问它之前,您应始终确认其容量。 您可以通过调用 getExternalStorageState() 查询外部存储状态。
如果返回的状态为 MEDIA_MOUNTED,那么您可以对您的文件进行读写。 例如,以下方法对于确定存储可用性非常有用:

/* Checks if external storage is available for read and write */

public boolean isExternalStorageWritable() {

String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state)) {

return true;

}

return false;

}


/* Checks if external storage is available to at least read */

public boolean isExternalStorageReadable() {

String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state) ||

Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {

return true;

}

return false;

}


   尽管外部存储可被用户和其他应用进行修改,但您可在此处保存两类文件 
   公共文件

应供其他应用和用户自由使用的文件。 当用户卸载您的应用时,用户应仍可以使用这些文件。
例如,您的应用拍摄的照片或其他已下载的文件。
   私有文件属于您的应用且在用户卸载您的应用时应予删除的文件。 尽管这些文件在技术上可被用户和其他应用访问(因为它们存储在外部存储中), 但它们实际上不向您的应用之外的用户提供任何输出值。 当用户卸载您的应用时,系统会删除应用外部私有目录中的所有文件。
例如,您的应用下载的其他资源或临时介质文件。
    如果您要将公共文件保存在外部存储设备上,请使用 
getExternalStoragePublicDirectory()
 方法获取表示外部存储设备上相应目录的 
File

该方法使用指定您想要保存以便它们可以与其他公共文件在逻辑上组织在一起的文件类型的参数,比如 
DIRECTORY_MUSIC
 或 
DIRECTORY_PICTURES
。例如:

public File getAlbumStorageDir(String albumName) {

// Get the directory for the user\'s public pictures directory.

File file = new File(Environment.getExternalStoragePublicDirectory(

Environment.DIRECTORY_PICTURES), albumName);

if (!file.mkdirs()) {

Log.e(LOG_TAG, "Directory not created");

}

return file;

}


       如果您要保存您的应用专用文件,您可以通过调用 
getExternalFilesDir()
 并向其传递指示您想要的目录类型的名称,从而获取相应的目录。通过这种方法创建的各个目录将添加至封装您的应用的所有外部存储文件的父目录,当用户卸载您的应用时,系统会删除这些文件。例如,您可以使用以下方法来创建个人相册的目录: 
  

public File getAlbumStorageDir(Context context, String albumName) {

// Get the directory for the app\'s private pictures directory.

File file = new File(context.getExternalFilesDir(

Environment.DIRECTORY_PICTURES), albumName);

if (!file.mkdirs()) {

Log.e(LOG_TAG, "Directory not created");

}

return file;

}


      如果没有适合您文件的预定义子目录名称,您可以改为调用 
getExternalFilesDir()
 并传递 
null
。这将返回外部存储上您的应用的专用目录的根目录。
       切记,
getExternalFilesDir()
 在用户卸载您的应用时删除的目录内创建目录。如果您正保存的文件应在用户卸载您的应用后仍然可用—比如,当您的应用是照相机并且用户要保留照片时—您应改用 
getExternalStoragePublicDirectory()

       无论您对于共享的文件使用getExternalStoragePublicDirectory()还是对您的应用专用文件使用 
getExternalFilesDir()
,您使用诸如 
DIRECTORY_PICTURES
 的
API 常数提供的目录名称非常重要。这些目录名称可确保系统正确处理文件。 例如,保存在 
DIRECTORY_RINGTONES
 中的文件由系统媒体扫描程序归类为铃声,而不是音乐。

二、可用空间
        如果您事先知道您将保存的数据量,您可以查出是否有足够的可用空间,而无需调用
getFreeSpace()
 或 
getTotalSpace()
 引起 
IOException
。这些方法分别提供目前的可用空间和存储卷中的总空间。
此信息也可用来避免填充存储卷以致超出特定阈值。

但是,系统并不保证您可以写入与 
getFreeSpace()
 指示的一样多的字节。如果返回的数字比您要保存的数据大小大出几
MB,或如果文件系统所占空间不到 90%,则可安全继续操作。否则,您可能不应写入存储。

注:保存您的文件之前,您无需检查可用空间量。 您可以尝试立刻写入文件,然后在 
IOException
 出现时将其捕获。
如果您不知道所需的确切空间量,您可能需要这样做。 例如,如果在保存文件之前通过将 PNG 图像转换成 JPEG 更改了文件的编码,您事先将不知道文件的大小。

三、删除文件

       您应始终删除不再需要的文件。删除文件最直接的方法是让打开的文件参考自行调用 
delete()

myFile.delete();

       如果文件保存在内部存储中,您还可以请求 
Context
 通过调用 
deleteFile()
 来定位和删除文件:
myContext.deleteFile(fileName);


:当用户卸载您的应用时,Android 系统会删除以下各项:
您保存在内部存储中的所有文件
您使用 
getExternalFilesDir()
 保存在外部存储中的所有文件。
但是,您应手动删除使用 
getCacheDir()
 定期创建的所有缓存文件并且定期删除不再需要的其他文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: