四种Android数据存储方式
Android提供以下四种存储方式:
- SharePreference
- SQLite
- File
- ContentProvider
Android系统中数据基本都是私有的,一般存放在“data/data/程序包名”目录下。如果要实现数据共享,正确的方式是使用ContentProvider。
SharedPreference
SharedPreference是一种轻型的数据存储方式,实际上是基于XML文件存储的“key-value”键值对数据。通常用来存储程序的一些配置信息。其存储在“data/data/程序包名/shared_prefs目录下。
SharedPreference本身只能获取数据,不支持存储和修改。存储和修改要通过Editor对象来实现。
1)、修改和存储数据
- 根据Context的getSharedPrerences(key,[模式])方法获取SharedPreference对象;
- 利用SharedPreference的editor()方法获取Editor对象;
- 通过Editor的putXXX()方法,将键值对存储数据;
- 通过Editor的commit()方法将数据提交到SharedPreference内。
综合例子:
//设置单例里面的数值,然后再将数值写入到SharedPreference里
privateStringsetCityName(String_cityName){
City.getCity().setCityName(_cityName);
Contextctx=MainActivity.this;
SharedPreferencessp=ctx.getSharedPreferences("CITY",MODE_PRIVATE);
Editoreditor=sp.edit();
editor.putString("CityName",City.getCity().getCityName());
editor.commit();
returnCity.getCity().getCityName();
}
2)、获取数据
- 同样根据Context对象获取SharedPreference对象;
- 直接使用SharedPreference的getXXX(key)方法获取数据。
综合例子:
//从单例里面找,如果不存在则在SharedPreferences里面读取
privateStringgetCityName(){
StringcityName=City.getCity().getCityName();
if(cityName==null||cityName==""){
Contextctx=MainActivity.this;
SharedPreferencessp=ctx.getSharedPreferences("CITY",MODE_PRIVATE);
City.getCity().setCityName(sp.getString("CityName","广州"));
}
returnCity.getCity().getCityName();
}
注意
getSharedPrerences(key,[模式])方法中,第一个参数其实对应到XML的文件名,相同key的数据会保存到同一个文件下。
使用SharedPreference的getXXX(key)方法获取数据的时候,如果key不存在的活,不会出现报错,会返回none。建议使用getXXX()的时候指定默认值。
SQLite
SQLite是一个轻量级关系型数据库,既然是关系型数据库,那操作起来其实跟mysql、sqlserver差不多的。
需要注意的一点是,SQLite只有NULL、INTEGER、REAL(浮点数)、TEXT(字符串)和BLOB(大数据)五种类型,不存在BOOLEAN和DATE类型。
1)、创建数据库
通过openOrCreateDatabase(Stringpath,SQLiteDatabase.CursorFactoryfactory)方法创建,如果库已创建,则打开数据库。
SQLiteDatabasedb=this.openOrCreateDatabase("test_db.db",Context.MODE_PRIVATE,null);2)、创建表
SQLiteDatabase没有提供创建表的方法,所以要靠execSQL()方法来实现。看名字也知道execSQL()用于直接执行sql的。
Stringsql="createtablet_user(idINTEGERPRIMARYKEYAUTOINCREMENT,nameTEXTNOTNULL,passwordTEXTNOTNULL)"; db.execSQL(sql);
增
使用SQLiteDatabase的insert(Stringtable,StringnullColumnHack,ContentValuesvalues)方法插入数据。ContentValues类,类似于java中的Map,以键值对的方式保存数据。
ContentValuesvalues=newContentValues();
values.put("name","liangjh");
values.put("password","123456");
db.insert("t_user","id",values);
删
删除数据就比较直接了。使用SQLiteDatabase的delete(Stringtable,StringwhereClause,String[]whereArgs)实现。如果不想把参数写在whereArgs里面,可以直接把条件写在whereClause里面。
//方式1直接将条件写入到条件里面(个人觉得容易被注入,但其实数据都在客户端,没啥安全性可言)
db.delete("t_user","id=1",null);
//方式2条件分开写,感觉比较安全
db.delete("t_user","name=?andpassword=?",newString[]{"weiyg","112233"});
查
查询有2个方法,query()和rawQuery()两个方法,区别在于query()是将sql里面的各参数提取出query()对应的参数中。可参考下面例子。
//使用rawQuery
//Cursorc=db.rawQuery("select*fromt_user",null);
//db.rawQuery("select*fromt_userwhereid=1",null);
//db.rawQuery("select*fromt_userwhereid=?",newString[]{"1"});
//使用query()
Cursorc=db.query("t_user",newString[]{"id","name"},"name=?",newString[]{"weiyg"},null,null,null);
c.moveToFirst();
while(!c.isAfterLast()){
Stringmsg="";
for(inti=0,j=c.getColumnCount();i<j;i++){
msg+="--"+c.getString(i);
}
Log.v("SQLite","data:"+msg);
c.moveToNext();
}
改
使用SQLiteDatabase的update(Stringtable,ContentValuesvalues,StringwhereClause,String[]whereArgs)可以修改数据。whereClause和whereArgs用于设置其条件。ContentValues对象为数据。
ContentValuesvalues=newContentValues();
values.put("password","111111");
//方式1条件写在字符串内
db.update("t_user",values,"id=1",null);
//方式2条件和字符串分开
db.update("t_user",values,"name=?orpassword=?",newString[]{"weiyg","123456"});
其它
无论何时,打开的数据库,记得关闭。
db.close()
另外使用beginTransaction()和endTransaction()可以设置事务。
File
文件储存方式,很久以前讲过,这里不说明。
ContentProvider
ContentProvider相对于其它的方式比较复杂,当然其功能相对于其它的方式也是革命性的改变。它能够实现跨应用之间的数据操作。利用ContentResolver对象的delete、update、insert、query等方法去操ContentProvider的对象,让ContentProvider对象的方法去对数据操作。实现方式为:
在A程序中定义一个ContentProvider,重载其增删查改等方法;
在A程序中的AndroidManifest.xml中注册ContentProvider;
在B程序中通过ContentResolver和Uri来获取ContentProvider的数据,同样利用Resolver的增删查改方法来获得和处理数据。
1)、在A程序定义一个Provider
新建一个类,继承ContentProvider,并重载其delete()、insert()、query()、update()、getType()、onCreate()方法。譬如下面的例子,重载其onCreate和query方法。
publicclassMyProviderextendsContentProvider{
@Override
publicintdelete(Uriuri,Stringselection,String[]selectionArgs){
//TODOAuto-generatedmethodstub
return0;
}
@Override
publicStringgetType(Uriuri){
//TODOAuto-generatedmethodstub
returnnull;
}
@Override
publicUriinsert(Uriuri,ContentValuesvalues){
//TODOAuto-generatedmethodstub
returnnull;
}
@Override
publicbooleanonCreate(){
//新建个数据库并插入一条数据
SQLiteDatabasedb=this.getContext().openOrCreateDatabase("test_db2.db",Context.MODE_PRIVATE,null);
db.execSQL("CREATETABLEt_user(idINTEGERPRIMARYKEYAUTOINCREMENT,nameTEXTNOTNULL)");
ContentValuesvalues=newContentValues();
values.put("name","liangjh2");
db.insert("t_user","id",values);
db.close();
returnfalse;
}
@Override
publicCursorquery(Uriuri,String[]projection,Stringselection,
String[]selectionArgs,StringsortOrder){
//获取数据
SQLiteDatabasedb=this.getContext().openOrCreateDatabase("test_db2.db",Context.MODE_PRIVATE,null);
Cursorc=db.query("t_user",null,null,null,null,null,null);
db.close();
returnc;
}
@Override
publicintupdate(Uriuri,ContentValuesvalues,Stringselection,
String[]selectionArgs){
//TODOAuto-generatedmethodstub
return0;
}
}
注册ContentProvider
在AndroidManifest.xml中声明ContentProvider,authorities属性定义了ContentProvider的Uri标识。关于Uri标识属另一个范畴,自行查询。provider标识要放在<application></application>里面。如果遇到了"PermissionDenial:openingprovide..."的错误,可以试试在节点加“android:exported="true"”。
<application...> ... <providerandroid:name=".MyProvider"android:authorities="com.example.androidtestdemo"android:exported="true"/> </application>
2)、在B程序获取数据
用Context获取到当前的ContentResolver,根据Uri地址和ContentResolver的query方法获取A程序的数据。Uri地址和A程序中AndroidManifest.xml定义的autorities要一致。当然,同类可以进行其它的操作。
Contextctx=MainActivity.this;
ContentResolverresolver=ctx.getContentResolver();
Uriuri=Uri.parse("content://com.example.androidtestdemo");
Cursorc=resolver.query(uri,null,null,null,null);
c.moveToFirst();
while(!c.isAfterLast()){
for(inti=0,j=c.getColumnCount();i<j;i++){
Log.v("Android2",""+c.getString(i));
}
c.moveToNext();
}
以上就是本文的全部内容,希望对大家的学习有所帮助。