安卓:可选的存储方式

Storage Options 可选的存储方式

STORAGE 快速预览

  • Use Shared Preferences for primitive data
  • Use internal device storage for private data
  • Use external storage for large data sets that are not private
  • Use SQLite databases for structured storage

在本文档中

  1. Using Shared Preferences
  2. Using the Internal Storage
  3. Using the External Storage
  4. Using Databases
  5. Using a Network Connection

另请参阅

  1. Content Providers and Content Resolvers

安卓提供了几种保存永久用户数据的方式。选择那种方式取决于你的实际需要:你想要似有还是和其他应用程序分享,以及你的数据需要的空间。

几种数据存储方式:

Shared Preferences
以键值对的方式存储似有原始数据。
Internal Storage
存储似有数据到设备存储器中。
External Storage
存储公有数据到可分享的外部存储器中。
SQLite Databases
存储结构化数据到私有数据库中。
Network Connection
使用你自有的网络服务存储数据到网络上。

安卓允许你使用 【内容提供者】来暴露数据,也包括私有数据。

Using Shared Preferences


SharedPreferences类提供了一个通用的框架允许你存储和检索原始数据类型的键值对。你可以使用SharedPreferences来保存任何原始数据:booleans, floats, ints, longs, 和 strings.数据通过用户序列保存(即使你的应用程序被杀死)。

为了获得SharedPreferences对象,可使用下面的一个或者两个方法:

  • 如果你需要多个preferences文件标识符,使用getSharedPreferences()。通过指定的第一个参数来标识名称。
  • 如果在Activity中仅使用一个preferences文件,使用getPreferences() 。不支持名称,只能使用一个。

写入值:

  1. 调用edit()来取得SharedPreferences.Editor对象。
  2. 使用方法诸如putBoolean() 和putString()等方法来添加值。
  3. 使用commit()来提交新值

为了读取值,使用SharedPreferences 的方法,例如getBoolean() and getString()

在计算器中静音键模式的preference保存例子:

public class Calc extends Activity {
    public static final String PREFS_NAME = "MyPrefsFile";

    @Override
    protected void onCreate(Bundle state){
       super.onCreate(state);
       . . .

       // 存储 preferences
       SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
       boolean silent = settings.getBoolean("silentMode", false);
       setSilent(silent);
    }

    @Override
    protected void onStop(){
       super.onStop();

      // 我们需要一个 Editor 对象来执行 preference 改变.
      // 所有这些对象都来自 android.context.Context
      SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
      SharedPreferences.Editor editor = settings.edit();
      editor.putBoolean("silentMode", mSilentMode);

      // Commit the edits!
      editor.commit();
    }
}

Using the Internal Storage 使用内部存储器


你可以直接在设备的内部存储器上保存文件。默认情况下保存在内部存储器的数据是私有的外部应用程序不可访问他们。当用户卸载你的应用程序时,这些文件将被移除。

创建和写一个私有文件于内部存储器上:

  1. 使用文件名和操作模式来调用openFileOutput() 。这将返回一个FileOutputStream对象。
  2. 使用write()来向文件写入数据。
  3. 使用close()来关闭流。

例子:

String FILENAME = "hello_file";
String string = "hello world!";

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();

MODE_PRIVATE将会创建(或者同名覆盖)并使其对于你的应用程序而言是私有的。其他可用模式:MODE_APPENDMODE_WORLD_READABLE, and MODE_WORLD_WRITEABLE.

从内部存储器读数据:

  1. 以读取文件的名字调用openFileInput()并返回FileInputStream对象                                                                                                            (函数原型:public abstract FileInputStream openFileInput (String name)
  2. 使用read()从文件读取字节
  3. 使用close()关闭流。

提示:如果你想在编译时保存静态文件,将文件保存在你工程下的res/raw/目录中。你可以使用openRawResource()打开它,传递R.raw.<filename>资源ID。这个方法返回一个你可用于读取的文件的InputStream(但你无法向原始文件中写入)

Saving cache files 保存缓存文件

如果你想要缓存一些数据,而不是永久储存他们,你应该使用getCacheDir()来打开代表内部存储临时文件的目录的File对象。

当你的设备内部存储空间不足时,安卓可能会删除这些缓存数据来回收空间。然而,你也不应该指望系统会为你清除这些文件。你应该自己维护这些缓存文件在合理的范围内,例如1MB。当用户删除你的应用程序时,这些文件将被移除。

Other useful methods  其他有用的方法

getFilesDir()
获得保存内部文件所在目录的文件系统的绝对路径。
getDir()

在内部存储空间中创建(或者打开一个已经存在的)目录。
deleteFile()

删除保存在内部储存中的一个文件
fileList()

返回你应用程序保存的当前文件列表

Using the External Storage  使用外部存储器


每一个安卓兼容的设备都支持可分享你保存的文件的“外部存储器”。它可以是可移动的存储媒介(例如SD 卡)或是内部(不可移动)的存储器。保存在外部存储器上的文件是全局可读的,并且在启用USB大存储来向电脑传输文件时它是可以被修改的。

设备使用部分内部存储作为外部存储之外还提供SD卡插槽。在这种情况下,SD卡不是外部存储的一部分,你的应用程序不能访问它。

警告:如果用户挂载外部存储到电脑或者移除媒介,外部存储器将不可用,并且也没有强制的安全来保存在外部存储上,所有的应用程序能够读写外部存储器上的文件,用户也可以移除他们。

Checking media availability  检查媒介可用性

在外部存储器上做任何事情之前,你应该总是调用 来检查媒介是否可用。媒介可能挂载到电脑上,丢失,只读或者在别的什么状态。下面的例子告诉你该如何做:

boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state)) {
    // 我们可以进行读写媒介
    mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
    // 我们只能读媒介
    mExternalStorageAvailable = true;
    mExternalStorageWriteable = false;
} else {
    // 这儿存在一些错误,处于其他的状态,我们所需要知道的,是我们无法进行读写操作
    mExternalStorageAvailable = mExternalStorageWriteable = false;
}

getExternalStorageState() 方法返回了你可能想要知道的状态,例如媒介正被分享,完全丢失了,或者被不正确的移除了等等。当应用程序访问媒介时,你可以使用状态来告知用户更多的信息。

Accessing files on external storage  在外部存储器上访问文件

如果你的API为8或者更高,使用getExternalFilesDir()来打开代表你存放文件的外部储存器目录。这个方法取得一个 类型参数,来指定你想要访问的子目录,例如DIRECTORY_MUSIC 和 DIRECTORY_RINGTONES(传递null来接收应用程序根目录)。这个方法会在合适的时候创建目录。通过指定目录类型,你确定媒介是合适的。如果用户删除应用程序,所有它的内容都会被删除。

如果是API7或者更低,使用getExternalStorageDirectory()来打开代表外部根目录的File。你应该像下面这样写入数据:

/Android/data/<package_name>/files/

<package_name>是JAVA风格的包名,如"com.example.android.app"。如果用户在API8或者更高API删除你的应用程序,所有内容将被删除。

Saving files that should be shared  保存需要被共享的文件

如果你想要保存文件,他们是与你的应用程序无关的,你应该保存在外部存储器的公有目录中。这些目录处于外部存储器的根目录下,如Music/Pictures/Ringtones/等等。

在API 8或者更高,使用getExternalStoragePublicDirectory()传递你想指定的参数,例如DIRECTORY_MUSIC,DIRECTORY_PICTURESDIRECTORY_RINGTONES等等。这个方法在需要时将会创建目录。

如果你使用API 7或者更低,使用getExternalStoragePublicDirectory()来打开代表根目录的File。然后保存共享的文件到下面的目录中:

  • Music/ - Media scanner classifies all media found here as user music. 用户音乐
  • Podcasts/ - Media scanner classifies all media found here as a podcast. 播客
  • Ringtones/ - Media scanner classifies all media found here as a ringtone. 手机铃音
  • Alarms/ - Media scanner classifies all media found here as an alarm sound. 闹铃声音
  • Notifications/ - Media scanner classifies all media found here as a notification sound.  通知声音
  • Pictures/ - All photos (excluding those taken with the camera). 图片
  • Movies/ - All movies (excluding those taken with the camcorder).  视频
  • Download/ - Miscellaneous downloads. 下载

Saving cache files  保存缓存文件

如果你的API为8或者更高,使用getExternalFilesDir()来打开代表你存放文件的外部储存器目录。删除程序时,他们会被删除,但是在程序生命周期中,如果你不删除他们,他们也不会自动删除。你应该管理他们,删除不用的。

如果你使用API 7或者更低,使用getExternalStoragePublicDirectory()来打开代表根目录的File,然后写到下面的目录中:

/Android/data/<package_name>/cache/

 <package_name> 是Java-style 包名, 例如 "com.example.android.app".

Using Databases 使用数据库


安卓提供了对于SQLite数据库完全的支持。你创建的数据库可以被你应用程序中的任何类通过名称访问,但在应用程序外部是不可以的。

一种推荐的创建 SQLite数据库的方法是,创建SQLiteOpenHelper子类对象,并重写它的onCreate()方法,在其中你可以执行SQLite命令来创建数据库表。例子如下:

public class DictionaryOpenHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 2;
    private static final String DICTIONARY_TABLE_NAME = "dictionary";
    private static final String DICTIONARY_TABLE_CREATE =
                "CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +
                KEY_WORD + " TEXT, " +
                KEY_DEFINITION + " TEXT);";

    DictionaryOpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DICTIONARY_TABLE_CREATE);
    }
}

使用你定义的结构体你可以获得SQLiteOpenHelper实现的实例。为了读写数据库,分别调用 getWritableDatabase() getReadableDatabase() 方法。他们都返回代表数据库和提供SQLite方法的 SQLiteDatabase对象

所有的SQLite查询将返回CursorCursor是一种机制,你可以导航结果然后获得行与列。你可以使用 SQLiteDatabasequery()执行查询,它接受一些参数: 查询表名, the projection, 选择参数, columns, 组, 以及其他。对于更加复杂的查询,如包含列别称的查询,你应该使用SQLiteQueryBuilder,它提供了一些便捷方法来构建查询。

SQLite使用的例子,查阅Note Pad and Searchable Dictionary应用。

Database debugging 数据库除错

安卓SDK包括了sqlite3数据库工具,允许你浏览表项,运行SQL语句,执行SQLite数据库的其他有用功能。查阅Examining sqlite3 databases from a remote shell 来获得更多有用信息。

Using a Network Connection  使用网络连接


你可以利用网络()在你拥有的网络服务上来存储或者检索数据。进行网络操作,使用下面这些包中的类:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值