Android数据存储

208 阅读9分钟

1、概述

  Android提供了5种方式来让用户保存持久化应用程序数据。根据自己的需求来做选择,比如数据是否是应用程序私有的,是否能被其他程序访问,需要多少数据存储空间等,分别是:

① 使用SharedPreferences存储数据

② 文件存储数据

③  SQLite数据库存储数据

④ 使用ContentProvider存储数据

⑤ 网络存储数据

Android提供了一种方式来暴露你的数据(甚至是私有数据)给其他应用程序ContentProvider。它是一个可选组件,可公开读写你应用程序数据。

2、SharedPreferences存储

  SharedPreference类提供了一个总体框架,使您可以保存和检索的任何基本数据类型( boolean, float, int, long, string)的持久键-值对(基于XML文件存储的“key-value”键值对数据)。

通常用来存储程序的一些配置信息。其存储在“data/data/程序包名/shared_prefs目录下。

xml 处理时Dalvik会通过自带底层的本地XML Parser解析,比如XMLpull方式,这样对于内存资源占用比较好。

2.1  我们可以通过以下两种方法获取SharedPreferences对象(通过Context):

① getSharedPreferences (String name, int mode)

当我们有多个SharedPreferences的时候,根据第一个参数name获得相应的SharedPreferences对象。

② getPreferences (int mode)

如果你的Activity中只需要一个SharedPreferences的时候使用

这里的mode有四个选项:

Context.MODE_PRIVATE

该SharedPreferences数据只能被本应用程序读、写。

Context.MODE_WORLD_READABLE

该SharedPreferences数据能被其他应用程序读,但不能写。

Context.MODE_WORLD_WRITEABLE

该SharedPreferences数据能被其他应用程序读和写。

Context.MODE_MULTI_PROCESS

sdk2.3后添加的选项,当多个进程同时读写同一个SharedPreferences时它会检查文件是否修改。 2.2  向Shared Preferences中写入值

首先要通过 SharedPreferences.Editor获取到Editor对象; 然后通过Editor的putBoolean() 或 putString()等方法存入值; 最后调用Editor的commit()方法提交;

//Use 0 or MODE_PRIVATE for the default operation SharedPreferences settings = getSharedPreferences("fanrunqi", 0); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean("isAmazing", true);

// 提交本次编辑 editor.commit();

同时Edit还有两个常用的方法:

editor.remove(String key) :下一次commit的时候会移除key对应的键值对

editor.clear():移除所有键值对

2.3  从Shared Preferences中读取值

  读取值使用 SharedPreference对象的getBoolean()或getString()等方法就行了(没Editor 啥子事)   
   SharedPreferences settings = getSharedPreferences("fanrunqi", 0);   
isAmazing= settings.getBoolean("isAmazing",true);

2.4  Shared Preferences的优缺点

可以看出来Preferences是很轻量级的应用,使用起来也很方便,简洁。但存储数据类型比较单一(只有基本数据类型),无法进行条件查询,只能在不复杂的存储需求下使用,比如保存配置信息等。

** 3.1 内部存储**

当文件被保存在内部存储中时,默认情况下,文件是应用程序私有的,其他应用不能访问。当用户卸载应用程序时这些文件也跟着被删除。

  文件默认存储位置:/data/data/包名/files/文件名。

 3.1.1 创建和写入一个内部存储的私有文件:

① 调用Context的openFileOutput()函数,填入文件名和操作模式,它会返回一个FileOutputStream对象。

② 通过FileOutputStream对象的write()函数写入数据。

③  FileOutputStream对象的close ()函数关闭流。

3.1.2 读取一个内部存储的私有文件:

① 调用openFileInput( ),参数中填入文件名,会返回一个FileInputStream对象。

② 使用流对象的 read()方法读取字节

③ 调用流的close()方法关闭流 其他一些经常用到的方法:

getFilesDir(): 得到内存储文件的绝对路径

getDir(): 在内存储空间中创建或打开一个已经存在的目录

deleteFile(): 删除保存在内部存储的文件。  

fileList(): 返回当前由应用程序保存的文件的数组(内存储目录下的全部文件)。 

3.1.3 保存编译时的静态文件

如果你想在应用编译时保存静态文件,应该把文件保存在项目的 res/raw/ 目录下,你可以通过 openRawResource()方法去打开它(传入参数R.raw.filename),这个方法返回一个 InputStream流对象你可以读取文件但是不能修改原始文件。

InputStream is = this.getResources().openRawResource(R.raw.filename);

3.1.4 保存内存缓存文件

有时候我们只想缓存一些数据而不是持久化保存,可以使用getCacheDir()去打开一个文件,文件的存储目录( /data/data/包名/cache )是一个应用专门来保存临时缓存文件的内存目录。

3.2 使用外部存储(sdcard) 因为内部存储容量限制,有时候需要存储数据比较大的时候需要用到外部存储,使用外部存储分为以下几个步骤:

3.2.1 添加外部存储访问限权

 首先,要在AndroidManifest.xml中加入访问SDCard的权限,

3.2.2 检测外部存储的可用性

 在使用外部存储时我们需要检测其状态,它可能被连接到计算机、丢失或者只读等。

3.2.3 访问外部存储器中的文件

1、如果 API 版本大于或等于8,使用

getExternalFilesDir (String type)

2、如果API 版本小于 8 (7或者更低)

getExternalStorageDirectory ()

4、 网络存储数据

HttpUrlConnection

HttpUrlConnection是Java.NET包中提供的API,我们知道Android SDK是基于Java的,所以当然优先考虑HttpUrlConnection这种最原始最基本的API,其实大多数开源的联网框架基本上也是基于JDK的HttpUrlConnection进行的封装罢了,掌握HttpUrlConnection需要以下几个步骤:

1、将访问的路径转换成URL。

URL url = new URL(path);

2、通过URL获取连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection();

3、设置请求方式。 conn.setRequestMethod(GET);

4、设置连接超时时间。 conn.setConnectTimeout(5000);

5、设置请求头的信息。 conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));

6、针对不同的响应码,做不同的操作(请求码200,表明请求成功,获取返回内容的输入流) 5、 SQLite数据库存储数据

Assets保存:用来存储一些只读数据,Assets是指那些在assets目录下的文件,这些文件在你将你的应用编译打包之前就要存在,并且可以在应用程序运行的时候被访问到。   但有时候我们需要对保存的数据进行一些复杂的操作,或者数据量很大,超出了文本文件和Preference的性能能的范围,所以需要一些更加高效的方法来管理,从Android1.5开始,Android就自带SQLite数据库了。

SQLite它是一个独立的,无需服务进程,支持事务处理,可以使用SQL语言的数据库。 5.1Android 中使用 SQLite

Activites 可以通过 Content Provider 或者 Service 访问一个数据库。 创建数据库   Android 不自动提供数据库。在 Android 应用程序中使用 SQLite,必须自己创建数据库,然后创建表、索引,填充数据。Android 提供了 SQLiteOpenHelper 帮助你创建一个数据库,你只要继承 SQLiteOpenHelper 类根据开发应用程序的需要,封装创建和更新数据库使用的逻辑就行了。 

SQLiteOpenHelper 的子类,至少需要实现三个方法: public class DatabaseHelper extends SQLiteOpenHelper {

/**
 * @param context  上下文环境(例如,一个 Activity)
 * @param name   数据库名字
 * @param factory  一个可选的游标工厂(通常是 Null)
 * @param version  数据库模型版本的整数
 * 
 * 会调用父类 SQLiteOpenHelper的构造函数
 */ 
public DatabaseHelper(Context context, String name, CursorFactory factory, int version) {
    super(context, name, factory, version);

}

/**
 *  在数据库第一次创建的时候会调用这个方法
 *  
 *根据需要对传入的SQLiteDatabase 对象填充表和初始化数据。
 */
@Override
public void onCreate(SQLiteDatabase db) {

}

/**
 * 当数据库需要修改的时候(两个数据库版本不同),Android系统会主动的调用这个方法。
 * 一般我们在这个方法里边删除数据库表,并建立新的数据库表.
 */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    //三个参数,一个 SQLiteDatabase 对象,一个旧的版本号和一个新的版本号

}

@Override
public void onOpen(SQLiteDatabase db) {
    // 每次成功打开数据库后首先被执行
    super.onOpen(db);
}

}

继承SQLiteOpenHelper之后就拥有了以下两个方法:

getReadableDatabase()  创建或者打开一个查询数据库

getWritableDatabase() 创建或者打开一个可写数据库

DatabaseHelper database = new DatabaseHelper(context);//传入一个上下文参数 SQLiteDatabase db = null; db = database.getWritableDatabase();

  上面这段代码会返回一个 SQLiteDatabase 类的实例,使用这个对象,你就可以查询或者修改数据库。  SQLiteDatabase类为我们提供了很多种方法,而较常用的方法如下: (int) delete(String table,String whereClause,String[] whereArgs)

删除数据行

(long) insert(String table,String nullColumnHack,ContentValues values) 添加数据行

(int) update(String table, ContentValues values, String whereClause, String[] whereArgs)

更新数据行

(void) execSQL(String sql) 执行一个SQL语句,可以是一个select或其他的sql语句

(void) close()

关闭数据库

(Cursor) query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)

查询指定的数据表返回一个带游标的数据集。

创建表和索引

db.execSQL("CREATE TABLE user(_id INTEGER PRIMARY KEY   
AUTOINCREMENT, username TEXT, password TEXT);");

添加数据 

①可以使用 execSQL() 方法执行 INSERT, UPDATE, DELETE 等语句来更新表的数据。execSQL() 方法适用于所有不返回结果的 SQL 语句。例如

String sql = "insert into user(username,password) values ('finch','123456');//插入操作的SQL语句
db.execSQL(sql);//执行SQL语句

②使用 SQLiteDatabase 对象的 insert()。

ContentValues cv = new ContentValues();
cv.put("username","finch");//添加用户名
cv.put("password","123456"); //添加密码
db.insert("user",null,cv);//执行插入操作

更新数据(修改)

①使用SQLiteDatabase 对象的 update()方法。

ContentValues cv = new ContentValues();
cv.put("password","654321");//添加要更改的字段及内容
String whereClause = "username=?";//修改条件
String[] whereArgs = {"finch"};//修改条件的参数
db.update("user",cv,whereClause,whereArgs);//执行修改

②使用execSQL方式的实现

String sql = "update [user] set password = '654321' where username="finch";//修改的SQL语句
db.execSQL(sql);//执行修改

查询数据

①使用 rawQuery() 直接调用 SELECT 语句

Cursor c = db.rawQuery("select * from user where username=?",new Stirng[]{"finch"});
if(cursor.moveToFirst()) {
  String password = c.getString(c.getColumnIndex("password"));
}

②通过query实现查询

Cursor c = db.query("user",null,null,null,null,null,null);//查询并获得游标
if(c.moveToFirst()){//判断游标是否为空
    for(int i=0;i<c.getCount();i++){&emsp;
c.move(i);//移动到指定记录
String username = c.getString(c.getColumnIndex("username");
String password = c.getString(c.getColumnIndex("password"));
    }
}

删除数据

①使用SQLiteDatabase 对象的delete()方法。

String whereClause = "username=?";//删除的条件
String[] whereArgs = {"finch"};//删除的条件参数
db.delete("user",whereClause,whereArgs);//执行删除

②使用execSQL方式的实现

String sql = "delete from user where username="finch";//删除操作的SQL语句
db.execSQL(sql);//执行删除操作