Android数据存储
Android数据存储
所有应用程序都会涉及数据的输入、输出,应用程序的参数设置、程序运行状态数据都需要保存到外部存储器上。
SharedPreferences
应用程序有少量的数据需要保存,而且这些数据的格式很简单,都是普通的字符串、标量类型的值等,可以使用SharedPreferences进行保存。
SharedPreferences与Editor
SharedPreferences保存的数据主要是类似于配置信息格式的数据,因此它保存的数据主要是简单类型的key-value对。
SharedPreferences接口主要负责读取应用程序的Preferences数据,它提供了如下常用方法来访问SharedPreferences中的key-value对:
- boolean contains(String key):判断SharedPreferences是否包含特定key的数据。
- abstract Map<String,?> getAll():获取SharedPreferences数据里全部的key-value对。
- boolean getXxx(String key , xxx defValue):获取SharedPreferences数据里指定key对应的value。如果该key不存在,则返回默认值defValue。其中xxx可以是boolean、float、int、long、String等各种基本类型的值。
SharedPreferences接口本身并没有提供写入数据的能力,而是通过SharedPreferences的内部接口,SharedPreferences调用edit()方法即可获取它所对应的Editor对象。Editor提供了如下方法来向SharedPreferences写入数据:
- SharedPreferences.Editor clear():清空SharedPreferences里所有数据。
- SharedPreferences.Editor putXxx(String key , xxx value):向SharedPreferences存入指定key对应的数据。其中xxx可以是boolean、float、int、long、String等各种基本类型的值。
- SharedPreferences.Editor remove(String key):删除SharedPreferences里指定key对应的数据项。
- boolean commit():当Editor编辑完成后,调用该方法修改。
Context提供的getSharedPreferences(String name , int mode)方法来获取SharedPreferences实例,这个方法的第二个参数支持如下几个值:
- Context.MODE_PRIVATE:指定该SharedPreferences数据只能被本应用程序读写。
- Context.MODE_WORLD_READABLE:指定该SharedPreferences数据能被其他应用程序读,但不能写。
- Context.MODE_WORLD_WRITEABLE:指定该SharedPreferences数据能被其他应用程序读写。
SharedPreferences数据总是保存在/data/data/<package name>/shared_prefs
目录下,以XML格式保存。
File存储
openFileOutput和openFileInput
Context提供了下面两个方法来打开应用程序的数据文件夹里的文件IO流:
- FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的name文件对应的输入流。
- FileOutputStream openFileOutput(String name , int mode):打开应用程序的数据文件夹下的name文件对应的输出流。
mode
指定打开文件的模式,支持如下所示的值:
- MODE_PRIVATE:该文件只能被当前程序读写。
- MODE_APPEND:以追加方式打开该文件,应用程序可以向该文件中追加内容。
- MODE_WORLD_READABLE:该文件的内容可以被其他程序读取。
- MODE_WORLD_WRITEABLE:该文件的内容可由其他程序读写。
Context还提供了下面几个方法可以访问应用程序的数据文件夹:
- getDir(String name , int mode):在应用程序的数据文件夹下获取或创建name对应的子目录。
- File getFilesDir():获取应用程序的数据文件夹的绝对路径。
- String[] fileList():返回应用程序的数据文件夹下的全部文件。
- deleteFile(String name):删除应用程序的数据文件夹下的指定文件。
读写SD卡上的文件
为了更好地存取应用程序中的大文件数据,应用程序需要读写SD卡上的文件。其步骤如下:
- 调用Environment的getExternalStorageState()方法判断手机上是否插入了SD卡,并且应用程序具有读写SD卡的权限。代码如下:
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
- 调用Environment的getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录。
- 使用FileInputStream、FileOutputStream、FileReader或FileWriter读写SD卡里的文件。
应用程序读写SD卡上的文件有如下两个注意点:
- 手机上应已插入SD卡。
- 为了读写SD卡上的数据,必须在应用程序的清单文件(AndroidManifest.xml)中添加读写SD卡的权限。例如如下代码:
<!--在SD卡中创建与删除文件权限-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!--向SD卡写入数据权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
SQLite数据库
Android系统集成了一个轻量级的数据库:SQLite。它只是一个嵌入式的数据库引擎,专门适用于资源有限的设备上适量数据存取。
SQLiteDatabase简介
Android提供了SQLiteDatabase代表一个数据库,一旦应用程序获得了其对象,就可以通过它来管理、操作数据库了。
SQLiteDatabase提供了如下方法打开一个文件对应的数据库:
- static SQLiteDatabase openDatabase(String path , SQLiteDatabase.CursorFactory factory , int flags):打开path文件所代表的SQLite数据库。
- static SQLiteDatabase openOrCreateDatabase(File file , SQLiteDatabase.CursorFactory factory):打开或创建(如果不存在)file文件所代表的SQLite数据库。
- static SQLiteDatabase openOrCreateDatabase(String path , SQLiteDatabase.CursorFactory factory):打开或创建(如果不存在)path文件所代表的SQLite数据库。
获取到SQLiteDatabase对象之后,就可调用SQLiteDatabase的如下方法操作数据库了:
- execSQL(String sql , Object[] bindArgs):执行带占位符的SQL语句。
- execSQL(String sql):执行SQL语句。
- insert(String table , ContentValues values , String whereClause , String[] whereArgs):更新指定表中的特定数据。
- update(String table , ContentValues values , String whereClause , String[] whereArgs):更新指定表中的特定数据。
- delete(String table , String whereCaluse , String[] whereArgs):删除指定表中的特定数据。
- Cursor query(String table , String[] columns , String whereClause , String[] whereArgs , String groupBy , String having , String orderBy):对指定数据表执行查询。
- Cursor query(String table , String[] columns , String whereClause , String[] whereArgs , String groupBy , String having , String orderBy,String limit):对指定数据表执行查询。
- Cursor query(boolean distinct , String table , String[] columns , String whereClause , String[] whereArgs , String groupBy , String having , String orderBy , String limit):对指定数据表执行查询。其中第一个参数控制是否去除重复值。
- rawQuery(String sql , String[] selectionArgs):执行带占位符的SQL查询。
- beginTransaction():开始事务。
- endTransaction():结束事务。
Cursor也提供了如下方法来移动查询结果的记录指针:
- move(int offset):将记录指针向上或向下移动指定的行数。offset为正数表示向下移动,为负数表示向上移动。
- boolean moveToFirst():将记录指针移动到第一行,如果成功则返回true。
- boolean moveToLast():将记录指针移动到最后一行,如果成功则返回true。
- boolean moveToNext():将记录指针移动到下一行,如果成功则返回true。
- boolean moveToPosition(int position):将记录指针移动到指定行,如果成功则返回true。
- boolean moveToPrevious():将记录指针移动到上一行,如果成功则返回true。
一旦将记录指针移动到指定行之后,就可以调用Cursor的getXxx()方法获取这一行的指定列的数据了。
创建数据库和表
如下代码表示在程序中创建数据表:
sql = "create table user_inf(user_id integer primary key , "+"user_name varchar(255),"+"user_pass varchar(255))"
db.execSQL(sql);
用SQLiteDatabase进行数据库操作的步骤如下:
- 获取SQLiteDatabase对象,它代表了与数据库的连接。
- 调用SQLiteDatabase的方法来执行SQL语句。
- 操作SQL语句的执行结果。
- 关闭SQLiteDatabase,回收资源。
使用特定方法操作SQLite数据库
1.使用insert方法插入记录
long insert(String table , String nullColumnHack , ContentValues values),这是插入方法,参数说明如下:
- table:代表想插入数据的表名;
- nullColumnHack:代表强行插入null值的数据列的列名。当values参数为null或不包含任何key-value对时该参数有效。
- values:代表一行记录的数据。
insert方法插入的一行记录使用ContentValues存放,ContentValues类似于Map,它提供了put(String key , Xxx value)方法用于存入数据,getAsXxx(String key)方法用于取出数据。
2.使用update方法更新记录
update(String table,ContentValues values,String whereClause,String[] whereArgs),参数说明如下:
- table:代表想更新数据的表名。
- values:代表想更新的数据。
- whereClause:满足该whereClause子句的记录将会被更新。
- whereArgs:用于为whereClause子句传入参数。
3.使用delete方法删除记录
delete(String table,String whereClause,String[] whereArgs),参数说明如下:
- table:代表想删除数据的表名。
- whereClause:满足该whereClause子句的记录将会被删除。
- whereArgs:用于为whereClause子句传入参数。
4.使用query方法查询记录
Cursor query(boolean distinct , String table , String[] columns , String whereClause , String[] whereArgs , String groupBy , String having , String orderBy , String limit),参数说明如下:
- distinct:指定是否去除重复记录;
- table:执行查询数据的表名;
- columns:要查询出来的列名。
- whereClause:查询条件子句。
- selectionArgs:用于为whereClause子句中的占位符传入参数值,值在数组中的位置与占位符在语句中的位置必须一致;否则就会有异常。
- groupBy:用于控制分组。
- having:用于对分组进行过滤。
- orderBy:用于对记录进行排序。
- limit:用于进行分页。
事务
SQLiteDatabase中包含如下两个方法来控制事务:
- beginTransaction():开始事务。
-
endTransaction():结束事务。
SQLiteDatabase还提供了如下方法来判断当前上下文是否处于事务环境中: - inTransaction():如果当前上下文处于事务中,则返回true,否则返回false。
当程序执行endTransaction()方法时将会结束事务(到底是提交事务,还是回滚事务),取决于SQLiteDatabase是否调用了setTransactionSuccessful()方法来设置事务标识,如果调用该方法设置了事务成功则提交事务,否则将会回滚事务。
SQLiteOpenHelper类
在实际项目中很少使用SQLiteDatabase的方法来打开数据库,通常都会继承SQLiteOpenHelper开发子类,并通过该子类的getReadableDatabase()、getWriteDatabase()方法打开数据库。
SQLiteOpenHelper包含如下常用方法:
- synchronized SQLiteDatabase getReadableDatabase():以读写的方式打开数据库对应的SQLiteDatabase对象。
- synchronized SQLiteDatabase getWritableDatabase():以写的方式打开数据库对应的SQLiteDatabase对象。
- abstract void onCreate(SQLiteDatabase db):当第一次创建数据库时回调该方法。
- abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):当数据库版本更新时回调该方法。
- synchronized void close():关闭所有打开的SQLiteDatabase对象。