Android数据保存方法
android数据保存主要保存以下三种:
1、共享参数文件中保存简单的键值对数据;
2、保存任意的文件数据到Android的文件系统中;
3、使用SQLite数据库管理
保存键值集
通过使用SharePreferences API来保存简单的键值对数据。
共享参数文件的获取或创建:
可以通过以下两种方法来获取:
getSharedPreferences() 该方法需要提供一个共享参数文件的名称标识,该方法可以在任意Context中调用
getPreferences() 使用该方法主要是为一个activity的私有数据存储使用,该方法不提供文件的名称。
eg:
Context context = getActivity();
SharedPreferences sharedPref = context.getSharedPreferences(getString(R.string.preference_file_key),Context.MODE_PRIVATE);
在该示例中,通过一个资源文件值:R.string.preference_file_key来指定了共享数据文件的名称。
如果要在一个Activity中使用唯一的一个共享数据文件,则可以使用下面的方法:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
注意:
在创建一个共享参数文件时,使用了 MODE_WORLD_READABLE 或者MODE_WORLD_WRITEABLE,则如果其他APP知道了该文件的名字标识,也可以访问该共享文件。
向共享参数文件中写入数据
通过调用SharedPreferecnes的edit()方法创建一个SharedPreferebces.Editor。 通过其putInt()、putString()等方法来写入相应的键值数据,并通过调用commit()来保存数据。
eg:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor eidtor = sharedPref.edit();
editor.putInt(getString(R.string.save_high_score),newHighScore);
editor.commit();
从共享参数文件中读取数据
通过调用getInt()、getString()方法来从共享参数文件中获取对应的值,并且可以提供一个默认的值,如果在共享参数文件中不存在该键值时,就使用默认值。
eg.
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
long highScore = sharedPref.getInt(getString(R.sting.saved_high_score),defaultValue);
将数据保存于文件中
内部和外部存储。
内部存储为默认的存储设备,如果希望数据为app私有(不被用户和其他app程序访问),则应将数据保存到内部存储设备上。
如果对存储数据没有访问限制,并且希望和其他APP或者用户访问,外部存储设备为最佳存储。
获取外部存储设备的访问许可
为了将数据保存到外部存储设备,必须在mainifest文件中请求WRITE_EXTERNAL_STORAGE权限:
<mainifets ...>
<uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE”/>
</manifest>
指定对外部存储的只读许可:
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
如果你的app使用WRITE_EXTERNAL_STORAGE许可,则同时也具有读外部存储的许可。
对于内部存储,我们不需要任何保存文件的许可,因为我们的应用程序总是具有内部存储的read和write文件的许可。
将文件保存到内部存储器
可以通过以下两种方法获取文件或者文件目录:
getFilesDir() 返回一个内部存储器上的文件夹
getCacheDir() 返回一个给当前app的内部存储器上的临时缓存文件,当在不需要使用该文件时,必须删除该文件,并且应指定一个合适的内存大小限制,比如1MB,如果系统开始运行缓慢,则会无警告的删除这些缓存文件。
可以通过上面的方法获取的文件夹在内部存储器上创建一个新的文件:
File file = new File(context.getFilesDir(),filename);
通过调用方法openFileOutput()去获取FileOutPutStream对象:
eg.
String filename = "myfile";
String string = "Hello world!";
FileOutPutStream outputStream;
try{
outputStream = openFileOutput(filename,Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
}catch(Exception e){
e.printStackTrace();
}
如果需要缓存一些文件,则调用createTempFile(),例如,下面的方法,从一个URL地址中提取文件名,并且用其在内部存储器缓存文件夹上创建一个文件。
public File getTempFile(Context context,String url){
File file;
try{
String filename = Uril.parse(url).getLastPathSegment();
file = File.createTempFile(filename,null,context.getCacheDir());
}catch(IOException e){
//
}
return file;
}
Note:
你的app的内部存储文件夹由你的app包名来指定,并存储在android文件系统的一个特殊位置。严格意义上讲,如果你设置了文件的mode为可读的(readable),其他app也可以读取你的内部文件。然而,其他app也需要知道你的app的包名和文件名。其他app不能浏览你的内部文件夹,并且不能read和write.除非你明确的设定了文件为readable或者writable,
将文件保存到外部存储器
在将文件写到外部存储器上之前,必须先检查外部存储器是否可用。通过调用方法getExternalStorageState()方法来查询外部存储器的状态,如果返回的状态为MEDIAZ_MOUNTED,则此时你可以在外部存储器上读写文件。
eg.
//该方法判断外部存储器是否挂载上(是否可读写)。
public boolean isExternalStorageWritable(){
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
returen true;
}
return false;
}
//检查外部存储器是否至少为可读的
public boolean isExternalStorageReadable(){
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEIDA_MOUNTED_READ_ONLY.equals(state)){
returen true;
}
return false;
}
虽然外部存储是用户或者其他app是可修改的,有两种文件你需要保存到这里:
共享文件
这种文件可以自由的被其他app和用户访问,当用户卸载掉app时,这些文件依然可以被用户访问。比如你的app的截图,或者其他下载文件。
私有文件
这些文件属于你的app,且这些文件在你卸载掉该app时也会被删除掉。虽然这些文件可以被用户和其他app访问,因为这些数据存储在外部存储器上的,实际上这些文件在自身的app以外不提供数据。比如通过你的app下载的额外的资源或者临时多媒体文件。
如果想保存一个公共文件到外部存储器,则使用方法:getExternalStoragePublicDirectory()来获取一个文件。该方法具有一个特定的参数来标识你想保存的文件类型。比如DIRECTORY_MUSI 或者 DIRECTORY_PICTURES.
eg.
//该方法获取用户的公共图片文件夹文件
public File getAlbumStorageDir(String albumName){
File file = new File(Environment.getExternalStoragePublicDirectory(Evironment.DIRECTORY_PICTURES),albumName);
if(!file.mkdirs()){
Log.e(LOG_TAG,"Directory not created");
}
return file;
}
如果要保存一个app的私有文件,可以通过调用方法getExternalFilesDir()
eg.下面的方法可以用来创建一个个人照片相册:
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;
}
记住getExternalFileDir()为在一个文件夹中创建一个文件夹且会在用户卸载掉当前app时删除掉创建的文件夹。如果想要在卸载时保存这些文件,则应该用方法:getExternalStoragePublicDirectory()方法代替。
查询剩余空间
我们没必要在写文件之前去检查存储盘的可用空间,我们可以通过对catch IOException 进行分析。
文件的删除
如果要删除一个文件,这可以直接调用delete()方法来删除。 eg. myFile.delete();
如果要删除的文件为内部存储器上的文件,则也可以调用Context的deleteFile()方法去删除该文件
eg:
myContext.deleteFile(fileName);
Note:
当用户在卸载app时,android系统会删除以下文件:
通过app保存到内部存储的所有文件;
通过getExternalFilesDir()方法保存到外部存储器的所有文件。
然而,你需要手动的删除所有通过getCacheDir()方法创建的文件。
将数据保存到SQL数据库中
定义数据库表结构
这里通过JAVA类定义了一个数据表的结构
public final class FeedReaderContract {
public FeedReaderContract() {}
//内部类定义表结构
public static abstract class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "entry";
public static final String COLUMN_NAME_ENTRY_ID = "entryid";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
...
}
}
使用SQL Helper 来创建一个数据库:
private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
FeedEntry._ID + " INTEGER PRIMARY KEY," +
FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
... // Any other options for the CREATE command
" )";
private static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
android将数据保存到程序的私有磁盘空间中,通常这里保存的数据不能被其他应用程序访问
要使用SQLiteOpenHelper类,需要实现其子类,该子类覆盖了onCreate(),onUpgrade(),onOpen()方法,你也可以。
public class FeedReaderDbHelper extends SQLiteOpenHelper {
// If you change the database schema, you must increment the database version.
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "FeedReader.db";
public FeedReaderDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// This database is only a cache for online data, so its upgrade policy is
// to simply to discard the data and start over
db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}
使用我们自定已的SQLiteOpenHelper类
FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());
向数据库中插入数据
通过使用ContentValues的instert()方法将数据插入到数据库中
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_ENTRY_ID,id)
values.put(FeedEntry.COLUMN_NAME_TITLE,title);
values.put(FeedEntry.COLUMN_NAME_CONTENT,content);
long newRowId;
newRowId = db.insert(FeedEntry.TABLE_NAME,
FeedEntry.COLUMN_NAME_NULLABLE,
values);
从数据库中读取数据
要从数据库中读取数据,使用query方法
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
FeedEntry._ID,
FeedEntry.COLUMN_NAME_TITLE,
FeedEntry.COLUMN_NAME_UPDATED,
...
};
// How you want the results sorted in the resulting Cursor
String sortOrder = FeedEntry.COLUMN_NAME_UPDATED + " DESC";
Cursor c = db.query(
FeedEntry.TABLE_NAME, // The table to query
projection, // The columns to return
selection, // The columns for the WHERE clause
selectionArgs, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);
读取Cursor中的数据cursor.moveToFirst();
long itemId = cursor.getLong(
cursor.getColumnIndexOrThrow(FeedEntry._ID)
);
删除数据库中的数据
String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(rowId) };
db.delete(table_name, selection, selectionArgs);
更新数据库数据
SQLiteDatabase db = mDbHelper.getReadableDatabase();
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(rowId) };
int count = db.update(
FeedReaderDbHelper.FeedEntry.TABLE_NAME,
values,
selection,
selectionArgs);