本文将简述Android API的数据储存 (Data Storage)工作机制,希望本文能对正在做Android开发的朋友有所帮助。
数据储存 (Data Storage)
Android为你提供了多个可选的方式来保存持久的应用数据。你可以基于特定的需求来选择解决方案,例如数据是否应该是你的应用私有的还是对其他应用(和用户)公开的以及你的数据需要多大的空间来储存。
你可选的数据储存方式如下:
◆Shared Preferences 共享偏好
以"键-值对"的形式储存私有的基础数据。
◆Internal Storage 内部存储器
储存私有数据到设备内存。
◆External Storage 外部存储器
储存公有数据到共享的外部储存器。
◆SQLite Databases SQLite数据库
用一个私有的数据库储存结构化数据。
◆Network Connection 网络连接
通过你自己的服务器储存数据到网络。
Android为你提供了一个途径来暴露你私有数据给其他的应用程序 —— 通过一个content provider 。一个content provider是一个可选组件,暴露你的应用程序数据的read/write接口,遵循任何可能引入的约定。更多关于content provider使用的信息,请查阅Content Providers 文档.
使用Shared Preferences (Using Shared Preferences)
SharedPreferences 类提供了一个通用的框架来允许你以"键-值对"的形式来储存和获取持久的基础数据。你可以使用SharedPreferences 来保存任何基础数据:boolean, float, int, long和String。这些数据将存留横跨用户对话(即使你的应用程序被杀死了)。
User Preferences Shared preferences are not strictly for saving "user preferences," such as what ringtone a user has chosen. If you're interested in creating user preferences for your application, see PreferenceActivity , which provides an Activity framework for you to create user preferences, which will be automatically persisted (using shared preferences). |
要给你的应用获取一个SharedPreference 对象,使用以下的两个函数之一:
getSharedPreferences() - 如果你需要多个通过名字来识别的偏好文件请使用该函数,名字通过***个参数来设定。
getPreferences() - 如果你的Activity仅需要一个偏好文件请使用该函数。因为这会是你的Activity独有的偏好文件,你不用提供一个文件名。
写入数值:
1.调用edit() 函数来获得一个SharedPreferences.Editor 对象。
2.通过putBoolean() 、putString() 等函数来添加数值。
3.通过commit() 函数来提交和确认操作。
要读取数值,使用SharedPreferences 中的getBoolean() 、getString() 等函数。
这里是一个例子,为一个计算器的按键静音模式保存了一个偏好:
Java代码
- public class Calc extends Activity {
- public static final String PREFS_NAME = "MyPrefsFile";
- @Override
- protected void onCreate(Bundle state) {
- super.onCreate(state);
- . . .
- // Restore preferences
- SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
- boolean silent = settings.getBoolean("silentMode", false);
- setSilent(silent);
- }
- @Override
- protected void onStop() {
- super.onStop();
- // We need an Editor object to make preference changes.
- // All objects are from 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() 函数来关闭流。
For example:
Java代码
- String FILENAME = "hello_file";
- String string = "hello world!";
- FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
- fos.write(string.getBytes());
- fos.close();
MODE_PRIVATE 会创建文件并使它对你的应用私有。其他可用的模式有:MODE_APPEND 、MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE。
要从内部存储器中读取一个文件:
1.调用openFileInput() 函数并传递一个文件名来读取。返回的是一个FileInputStream 对象。
2.使用read() 函数读取文件中的字节。
3.然后使用close() 函数关闭流。
提示 :如果你希望在编译的时候保存一个静态的文件到你的应用中,将文件保存到你项目的res/raw/ 目录下。你使用openRawResource() 函数可以打开它,传递一个R.raw.<filename> 资源ID。该函数返回一个你可以用来读取文件的InputStream 对象(但你无法改写原始文件)。
保存缓存文件 (Saving cache files)
如果你想缓存一些数据,而不是***储存,你应该使用getCacheDir() 来打开一个代表内部存储器中储存临时缓存文件的目录的File 对象。
当设备的内部储存空间较低时,Android可能会删除这些缓存文件来取回空间。无论如何,你不应该依靠系统来为你清空这些文件。你应该始终自己来维护缓存文件并维持在一个合理的空间消耗,比如1MB。当用户卸载你的应用,这些文件会被移除。
其他有用的函数 (Other useful methods)
◆getFilesDir()
获取你的内部文件所储存的系统目录的绝对路径。
◆getDir()
在你的内部存储器空间中创建(或打开一个存在的)目录。
◆deleteFile()
删除一个保存在内部存储器上的文件。
◆fileList()
返回一个你的应用当前保存了的文件的数组。#p#
使用外部存储器 (Using the External Storage)
每个兼容Android的设备都支持一个共享的"外部存储器",你可以用它来储存文件。这可以是可被移除的存储媒介(例如一个SD卡)或是一个内部存储器 (不可被移除)。储存在外部存储器中的文件都是world-readable属性并且可以被用户修改(当他们允许USB大储存器在电脑上转移文件时)。
警告 :里面的这些外部文件是会消失不可见的——如果用户把外部存储器挂在到一台电脑上或移除该媒介(SD卡),同时你储存在外部储存器上的文件没有强制的安全保证。所有应用程式都可以读写这些文件并且用户也可以删除它们。 |
检测媒介是否可用 (Checking media availability)
在你对外部存储器进行任何操作之前,你应该始终调用getExternalStorageState() 函数来检测媒介是否处于可用状态。媒介可能被挂载到一台电脑上、遗失、只读或处于其他状态。例如,你可以像这里这样来检测其是否可用:
Java代码
- boolean mExternalStorageAvailable = false;
- boolean mExternalStorageWriteable = false;
- String state = Environment.getExternalStorageState();
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- // We can read and write the media
- mExternalStorageAvailable = mExternalStorageWriteable = true;
- } else
- if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state))
- {
- // We can only read the media
- mExternalStorageAvailable = true;
- mExternalStorageWriteable = false;
- } else {
- // Something else is wrong. It may be one of many other states, but all we need
- // to know is we can neither read nor write
- mExternalStorageAvailable = mExternalStorageWriteable = false;
- }
这个例子检测外部存储器是否可用于读和写。你可能希望检测getExternalStorageState() 函数返回的其他状态,例如媒介是否被共享了(连接到了电脑)、是否完全遗失了、被意外移除了等等。当你的应用需要访问媒介的时候,你可以使用这些(携带更多的信息)来提示用户。
访问外部存储器上的文件 (Accessing files on external storage)
如果你使用的是API Level 8或更高版本,使用getExternalFilesDir() 函数来打开一个代表外部存储器目录(你最终储存文件的地方)的File 对象。该函数使用一个type 参数来指定你希望的子目录的类型,例如 DIRECTORY_MUSIC 和 DIRECTORY_RINGTONES (传null 值,会返回你应用文件目录的根目录)。该函数会在需要时创建合适的目录。
如果你使用的是API Level 7或更低的版本,使用getExternalStorageDirectory() 函数来打开一个代表外部存储器根目录的File 对象。然后,你应该将你的数据写入到以下的目录:
/Android/data/<package_name> /files/<package_name> 是你的Java风格的包名,比如"com.example.android.app "。如果用户的设备正在运行的是API Level 8或更高的版本,那么在你的应用被卸载后,该目录及其中的所有内容都将被删除掉。
从Media Scanner中隐藏你的文件 包含一个命名为 .nomedia 的空文件到你的外部文件目录(注意文件名中的点前缀)。这样会防止Android的media scanner通过读取你的媒介文件并包含他们到应用中,想画廊或音乐。 |
保存可被共享的文件 (Saving files that should be shared)
如果你希望保存的文件并不特定于你的应用并且不会在应用卸载时被删除,请将他们保存到外部存储器上的一个公有目录。这些目录放置在外部存储器的根目录下,比如 Music/ , Pictures/ , Ringtones/ 及其他。
在API Level 8或更高版本中,使用 getExternalStoragePublicDirectory() 函数,传给它一个你希望的公有目录类型,比如 DIRECTORY_MUSIC , DIRECTORY_PICTURES, DIRECTORY_RINGTONES或其他。该函数将在必要的时候创建合适的目录。
如果你使用的是API Level 7或更低的版本,使用getExternalStorageDirectory() 函数来打开一个代表外部存储器根目录的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 Level 8或更高的版本,使用getExternalCacheDir() 函数来打开一个代表外部存储器中你将储存缓存文件的目录的File 对象。如果用户卸载你的应用,这些文件将会被自动删除。无论如何,在你应用的生命中,你应该管理这些缓存文件并在不再需要的时候移除它们以便保存文件空间。
如果你使用的是API Level 7或更低的版本,使用getExternalStorageDirectory() 函数来打开一个代表外部存储器根目录的File 对象,然后将你的缓存数据写入到下面的目录:/Android/data/<package_name> /cache/<package_name> 是你的Java风格的包名,比如"com.example.android.app "。
使用数据库 (Using Databases)
Android提供了对SQLite 数据库的完整支持。任何你所创建的数据库在应用中的任何一个类中都可以通过其文件名来访问到,但无法在应用外部访问。
创建一个新的SQLite数据库,推荐的方式是创建一个SQLiteOpenHelper 的子类并重写其onCreate() 函数,在该函数中执行SQLite命令来在数据库中创建表。例如:
Java代码
- 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() 函数分别来写进或读出数据,两个函数都会返回一个表示数据库的SQLiteDatabase 对象,并为SQLite的操作提供了函数。
Android没有在标准的SQLite概念上添加任何限制。我们推荐包含一个自动增量数值键字段来被用于作为一个***的ID,以便快速找到一个记录。这不需要是一个私有数据,但如果你实现了一个 content provider ,你就必须使用BaseColumns._ID 常量来包含一个***的ID。 |
你可以使用SQLiteDatabase 的query() 函数来执行SQLite的查询,query() 函数支持各种查询参数,例如查询表时就有projection, selection, columns, grouping等参数可配置。对于复杂的查询,例如那些需要列别名的,你应该使用SQLiteQueryBuilder ,它提供了多个便捷的函数可用于构建查询。
每个SQLite查询都会返回一个Cursor 对象,它指向查询所找到的所有的行。Cursor 永远是你操纵数据库查询结果及读取行和列的途径。
作为Android中展示了如何使用SQLite数据库的例子,请查看Note Pad 和Searchable Dictionary 应用。
数据库调试 (Database debugging)
Android SDK包含了一个数据库工具来允许你浏览表格的内容,在SQLite数据库上运行SQL命令,并执行其他有用的方法。查阅Examining sqlite3 databases from a remote shell 学习如何运行该工具。
使用网络连接 (Using a Network Connection)
你可以在你自己的基于网络的服务器上使用网络(当它可用的时候)来储存和接收数据。要执行网络操作,使用下面的包中的类:java.net.* android.net.*
原文请查阅:http://developer.android.com.nyud.net/guide/topics/data/data-storage.html
【编辑推荐】