一.Android数据的存储方式
Android提供以下几种存储方式:
1 使用SharedPreferences存储数据
2 文件存储数据
3 SQLite数据库存储数据
4 使用ContentProvider存储数据
5 网络存储数据
Android系统中数据基本都是私有的,一般存放在“data/data/程序包名
”目录下。如果要实现数据共享,正确的方式是使用ContentProvider
。
(一)SharedPreference
SharedPreference
是一种轻型的数据存储方式,实际上是基于XML文件存储的“key-value
”键值对数据。通常用来存储程序的一些配置信息。其存储在“data/data/程序包名/shared_prefs
“目录下。
SharedPreference
本身只能获取数据,不支持存储和修改。存储和修改要通过Editor对象来实现。
修改和存储数据
- 根据Context的getSharedPrerences(key, [模式])方法获取SharedPreference对象;
- 利用SharedPreference的editor()方法获取Editor对象;
- 通过Editor的putXXX()方法,将键值对存储数据;
例子:
设置单例里面的数值,然后再将数值写入到SharedPreference里
private String setCityName(String _cityName){
City.getCity().setCityName(_cityName);
Context ctx =MainActivity.this;
SharedPreferences sp =ctx.getSharedPreferences("CITY", MODE_PRIVATE);
Editor editor=sp.edit();
editor.putString("CityName", City.getCity().getCityName());
editor.commit();
return City.getCity().getCityName();
}
获取数据
- 同样根据Context对象获取SharedPreference对象;
- 直接使用SharedPreference的getXXX(key)方法获取数据。
从单例里面找,如果不存在则在SharedPreferences里面读取
private String getCityName(){
String cityName = City.getCity().getCityName();
if(cityName==null ||cityName==""){
Context ctx =MainActivity.this;
SharedPreferences sp =ctx.getSharedPreferences("CITY", MODE_PRIVATE);
City.getCity().setCityName(sp.getString("CityName", "广州"));
}
return City.getCity().getCityName();
}
注意
- getSharedPrerences(key, [模式])方法中,第一个参数其实对应到XML的文件名,相同key的数据会保存到同一个文件下。
- 使用SharedPreference的getXXX(key)方法获取数据的时候,如果key不存在的活,不会出现报错,会返回none。建议使用getXXX()的时候指定默认值。
(二)SQLite
SQLite是一个轻量级关系型数据库,既然是关系型数据库,那操作起来其实跟mysql、sql server差不多的。
需要注意的一点是,SQLite只有NULL、INTEGER、REAL(浮点数)、TEXT(字符串)和BLOB(大数据)五种类型,不存在BOOLEAN和DATE类型。
特点:
面向资源有限的设备,
没有服务器进程,
所有数据存放在同一文件中跨平台,
可自由复制。
SQLite 内部结构:
下面会详细讲解如果创建数据库,添加数据和查询数据库。 创建数据库 Android 不自动提供数据库。在 Android 应用程序中使用 SQLite,必须自己创建数据库,然后创建表、索引,填充数据。
创建数据库
通过openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory)
方法创建,如果库已创建,则打开数据库。
SQLiteDatabase db =this.openOrCreateDatabase("test_db.db", Context.MODE_PRIVATE, null);
创建表
SQLiteDatabase
没有提供创建表的方法,所以要靠execSQL()
方法来实现。看名字也知道execSQL()
用于直接执行sql的。
String sql="create table t_user (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL,password TEXT NOT NULL)";
db.execSQL(sql);
增加
使用SQLiteDatabase的insert(String table, String nullColumnHack, ContentValues values)
方法插入数据。ContentValues
类,类似于java中的Map,以键值对的方式保存数据。
ContentValues values=new ContentValues();
values.put("name", "liangjh");
values.put("password", "123456");
db.insert("t_user", "id", values);
删除
删除数据就比较直接了。使用SQLiteDatabase
的delete(String table, String whereClause, String[] whereArgs)
实现。如果不想把参数写在whereArgs
里面,可以直接把条件写在whereClause
里面。
// 方式1 直接将条件写入到条件里面(个人觉得容易被注入,但其实数据都在客户端,没啥安全性可言)
db.delete("t_user", "id=1", null);
// 方式2 条件分开写,感觉比较安全
db.delete("t_user", "name=? and password =?", new String[]{
"weiyg","112233"});
查询
查询有2个方法,query()
和rawQuery()
两个方法,区别在于query()
是将sql里面的各参数提取出query()对应的参数中。可参考下面例子。
// 使用rawQuery
// Cursor c = db.rawQuery("select * from t_user", null);
// db.rawQuery("select * from t_user where id=1", null);
// db.rawQuery("select * from t_user where id=?", new String[]{"1"});
// 使用query()
Cursor c = db.query("t_user", new String[]{
"id","name"}, "name=?", new String[]{
"weiyg"}, null, null, null);
c.moveToFirst();
while(!c.isAfterLast()){
String msg="";
for(int i=0,j=c.getColumnCount();i<j;i++){
msg+="--"+c.getString(i);
}
Log.v("SQLite", "data:"+msg);
c.moveToNext();
}
修改
使用SQLiteDatabase的update(String table, ContentValues values, String whereClause, String[] whereArgs)
可以修改数据。whereClause
和whereArgs
用于设置其条件。ContentValues
对象为数据。
ContentValues values=new ContentValues();
values.put("password", "111111");
// 方式1 条件写在字符串内
db.update("t_user", values, "id=1", null);
// 方式2 条件和字符串分开
db.update("t_user", values, "name=? or password=?",new String[]{
"weiyg","123456"});
其它
无论何时,打开的数据库,记得关闭。
db.close()
另外使用beginTransaction()
和endTransaction()
可以设置事务。
(三)File
关于文件存储,Activity提供了openFileOutput()
方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的。
文件可用来存放大量数据,如文本、图片、音频等。
默认位置:/data/data/<包>/files/...
。
public void save()
{
try {
FileOutputStream outStream=this.openFileOutput("a.txt",Context.MODE_WORLD_READABLE);
outStream.write(text.getText().toString().getBytes());
outStream.close();
Toast.makeText(MyActivity.this,"Saved",Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
return;
}
catch (IOException e){
return ;
}
}
openFileOutput()
方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。
创建的文件保存在/data/data/<package name>/files
目录,如: /data/data/cn.itcast.action/files/itcast.txt
,通过点击Android Studio菜单“Tools”-“Android”-“Android Device Monitor,在项目中打开/data/data/<package name>/files
目录就可以看到该文件。
openFileOutput()
方法的第二参数用于指定操作模式,有四种模式,分别为:
Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2
Context.MODE_PRIVATE:
为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND:
模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE
和Context.MODE_WORLD_WRITEABLE
用来控制其他应用是否有权限读写该文件。
MODE_WORLD_READABLE:
表示当前文件可以被其他应用读取;
MODE_WORLD_WRITEABLE:
表示当前文件可以被其他应用写入。
如果希望文件被其他应用读和写,可以传入: openFileOutput(“itcast.txt”, Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
android有一套自己的安全模型,当应用程序(.apk)在安装时系统就会分配给他一个userid,当该应用要去访问其他资源比如文件的时候,就需要userid匹配。默认情况下,任何应用创建的文件,sharedpreferences
,数据库都应该是私有的(位于/data/data/<package name>/files
),其他程序无法访问。
除非在创建时指定了Context.MODE_WORLD_READABLE
或者Context.MODE_WORLD_WRITEABLE
,只有这样其他程序才能正确访问。
public void load()
{
try {
FileInputStream inStream=this.openFileInput("a.txt");
ByteArrayOutputStream stream=new ByteArrayOutputStream();
byte[] buffer=new byte[1024];
int length=-1;
while((length=inStream.read(buffer))!=-1) {
stream.write(buffer,0,length);
}
stream.close();
inStream.close();
text.setText(stream.toString());
Toast.makeText(MyActivity.this,"Loaded",Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e){
return ;
}
}
对于私有文件只能被创建该文件的应用访问,如果希望文件能被其他应用读和写,可以在创建文件时,指定Context.MODE_WORLD_READABLE
和Context.MODE_WORLD_WRITEABLE
权限。
Activity还提供了getCacheDir()和getFilesDir()
方法: getCacheDir()
方法用于获取/data/data/<package name>/cache
目录 getFilesDir()
方法用于获取/data/data/<package name>/files
目录。
把文件存入SDCard:
使用Activity的openFileOutput()
方法保存文件,文件是存放在手机空间上,一般手机的存储空间不是很大,存放些小文件还行,如果要存放像视频这样的大文件,是不可行的。对于像视