Android系统中的数据存储区方式有五种:
五种数据存储方式
1.文件存储:以I/O流的形式把数据存入手机内存或SD卡,可以存储大数据。
2.SharedPreference:本质是一个XML文件,以Map<Object,Object>
形式存入手机内存中。
3.SQLite数据库:SQLite是一个轻量级、跨平台的数据库。数据库中所有信息都存储在单一文件内,占用内存小,并且支持SQL语法,通常用于存储用户信息。
4.ContentProvider:内容提供者,是Android四大组件之一,以数据库形式存入手机内存,可以共享自己的数据给其他应用使用。
5.网络存储:把数据存储到服务器,不存储在本地,使用的时候直接从网络获取。
文件存储
1.内部存储:将应用程序中的数据以文件形式存储到设备的内部存储空间中,内部存储方式存储的文件被其所创建的应用程序私有。
内部存储使用的是Context提供的openFileOutput()方法和openFileInput()方法,分别获取FileOutputStream对象和FileInputStream对象。
参数name表示文件名
mode表示文件的操作模式
MODE_PRIVATE:该文件只能被当前程序读写,默认操作模式
MODE_APPEND:该文件可以追加内容,常用模式
MODE_WORLD_READABLE:该文件的内容可以被其他文件读取,安全性低。
MODE_WORLD_WRITEABLE:该文件的内容可以被其他程序写入,安全性低。
存储数据:
String fileName="data.txt";//文件名称
String content="helloworld";//保存数据
FileOutPutStream fos;
try{
fos=openFileOutput(FileName,MODE_PRIVATE);
fos.write(content.getBytes());
fos.close();
}catch(Exception e){
e.printStackTrace();
}
取出数据:
String Content="";
FileInputStream fis;
try{
fis=openFileInput("data.txt");
byte[] buffer=new byte[fis.available()];
fis.read(buffer);
content=new String(buffer);
}catch(Exception e){
e.printStackTrace();
}
2.外部存储:将文件存储到一些外围设备上。
由于外围存储设备可能被移除、丢失、或者出其他状态,因此在使用外围设备之前必须使用Environment.getExternalStorageState()方法来确认外围设备是否可用。通过FileInputStream、FileOutputStream或者FileReader、FileWriter对象来读写外围设备中的文件。
从外围设备存储数据:
String state=Environment.getEcternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
File SDPath=Environment.getExternalStorageDriectory();
File file=new File(SDPath,"data.txt");
String data="HelloWorld";
FileOutputStream fos;
try{
fos=new FileOutputStream(file);
fos.write(data.getBytes());
fos.close();
}catch(Exception e){
e.printStackTrace();
}
从外围设备中读取数据:
String state=Environment.getExternalStorageState();
if(State.equals(Environment.MEDIA_MOUNTED)){
File SDPath=Environment.getExternalStorageDirectory();
File file=new File(SDPath,"data.txt");
FileInputStream fis;
try{
fis=new FileInputStream(file);
BufferedReader br=new BufferedReader(new InputStreamReader(fis));
String data=br.readLine();
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
SharedPerferences
是Android平台上以个轻量级的存储类,主要用于存储一些应用程序的配置参数。SharedPerference中存储的数据是以key/value键值对的形式保存在XML文件中,该文件位于data/data/<packagename>/shared_prefs
文件夹中。需要注意的是,SharedPerferences中的value只能是float、int、long、boolean、String、StringSet类型。
使用SharedPerferences类存储数据时,首先需要通过context.getSharedPerferences获取SharedPerferences的实例对象。
(PS:SharedPreferences对象本身只能获取数据,并不支持数据的存储和修改)
数据的存储和修改需要通过SharedPerferences.Editor()对象实现。
通过Editor对象相关方法存储数据:
SharedPerferences sp=getSharedPerferences("data",MODE_PERIVATE);
Eidtor editor=sp.edit();// 获取编辑器
editor.putString("name","小白");//存入String类型数据
editor.putInt("age",8);//存入Int类型数据
editor.commit();//提交修改
使用对象获取相应的key值即可:
SharedPerferences sp=context.getSharedPreferences();
String data=sp.getString("name","");//获取用户名
通过该对象删除数据:
SharedPerferences sp=context.SharedPerferences();
Editor editor=sp.edit();
editor.remove("name");//删除一条数据
editor.clear();
editor.commit();
SQLite数据库
SQLite遵循ACID关联的数据库管理系统。
ACID:原子性,一致性,隔离性,持久性。
SQLite没有服务进程,通过文件保存数据,该文件是跨平台。
支持NULL,INTEGER,REAL,TEXT,BLOB.
实际上SQLite也接受varchar,char,decimal等数据类型。
只不过在运算或保存时转换成对应的五种数据类型。
1.创建SQLite数据库
public class PersonSQLiteOpenHelper extends SQLiteOpenHelper{
//数据库的构建方法,用来定义数据库的名称,数据库查询的结果,数据库的版本
public PersonSQLiteOpenHelper(Context context){
super(context,"person.db",null,5);
}
//数据库第一次被创建时调用该方法
public void OnCreate(SQLiteDatabase db){
//初始化数据库的表结构,执行一条键表的SQL语句
db.execSQL("create table person(
id integer primary key autoincrement,"+
"name varchar(20),"+
"number varchar(20)");
}
//当数据库的版本号增加时调用
public void onUpgrade(SQLiteDatabase db,int oldVesion, int newVersion){
db.execSQL("alter table person add account varchar(20);
}
}
2.添加数据
public long add(String name,String number){
//拿到一个读写的SQLiteDatabase对象
SQLiteDatabase db=helper.getWritableDatabase();
//将参数名和列添加到ContentValues对象里面
ContentValues values=new ContentValues();
values.put("name",name);
values.put("number",number);
//输入数据到person表里
long id=db.insert("person",null,values);
//关闭数据库
db.close();
return id;
db.execSQL(“insert into person(name ,number) value(?,?)”,new Object[]{name,number})
3.修改数据
public int update(String name,String newnumber){
//拿到一个读写的SQLiteDatabase对象
SQLiteDatabase db=helper.getWritableDatabase();
//将参数名和列添加到ContentValues对象里面
ContentValues values=new ContentValues();
//将参数以key,values
values.put("number",newnumber);
//输入数据到person表里
int number=db.update("person",values,"name=?",new String []{name});
//关闭数据库
db.close();
return id;
4.删除数据
public int delete(String name){
//拿到一个读写的SQLiteDatabase对象
SQLiteDatabase db=helper.getWritableDatabase();
//删除数据
int number=db.delete("person","name=?",new String []{name});
//关闭数据库
db.close();
return number;
5.查询数据
public boolean find(String name){
//获取一个可读的数据库
SQLiteDatabase db=helper.getReadableDatabase();
//查询数据库的操作 参数1:表名,参数2:查询的列名,参数3:查询条件
//参数4:查询参数值,参数5:分组条件 参数6:having条件,参数7:排列方式
Cursor cursor=db.query("person",null,"name=?",new String[] {name},null,null,null);
//是否有下一条值
boolean result=cursor.moveToNext();
//关闭游标
cursor.close();
//关闭数据库
db.close();
return result;
}
rawQuery()方法执行SQL语句
Cursor cursor=db.rawQuery(“select * from person where name=?”,new String []{name});
5.SQLite事务操作
PersonSQLiteOpenHelper helper =new PersonSQLiteOpenHelper(getContext());
//获取一个可写的SQLiteDatabase
SQLiteDatabase db=helper.getWritableDatabase();
//开始数据库的事务
db.beginTransaction();
try{
//执行转出操作
db.execSQL("update person set account=account-1000 where name=?",new Object[]{"zhangsan"};
//执行转入操作
db.execSQl("update person set account=account+1000 where name=?",new Object []{"wangwu"});
//标记数据库事务执行成功
db.setTransactionSuccessful();
}catch(Exception e){
Log.i("事务处理失败",e.toString());
}finally{
db.endTransaction();//关闭事务
db.close();//关闭数据库
}
}
ContentProvider
是Android系统四大组件之一,用于保存和检索数据,是android系统中不同应用程序之间共享数据的接口。
是不同应用程序之间进行数据交换的标准API,以Uri的形式对外提供数据,允许其他应用操作本应用数据。
1.创建内容提供者
首先定义一个类继承android.conten包下的ContentProvider类。在使用该类时需要重写它的onCreate()、delete()、getType()、insert()、query()、update()这几个抽象方法。
如果指定数据的类型属于集合型,getType()方法返回的字符串应该以“vnd.android.cursor.dir/”开头。
如果属于非集合类型则返回的字符串以“vnd.android.cursor.item/”.
创建者内容提供:
public class PersonDBProvider extends ContentProvider{
public boolean onCreate(){
return false;
}
public Cursor query(Uri uri,String [] projection,String selection,String [] selectionArgs,String sortOrder){
return null;
}
public String getType(String uri){
return null;
}
public Uri insert (Uri uri,ContentValues values){
return null;
}
public int delete(Uri String selection ,String [] selectionArgs){
return 0;
}
public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){
return 0;
}
}
注册内容提供者:
<provider
android:name="cn.itcast.db.PersonDBProvider"
android:authorities="cn.itcast.db.personprovider">
</provider>
当使用provider暴露敏感的数据时,为了数据安全,在注册ContentProvider时,还可以为其指定权限。
android:permission属性:如果注册provider时使用了该属性,那么其他程序在访问ContentProvider时必须加上权限,否则会报异常。
例如:
PersonDBProvider注册了android:permission=”mobile.permission android:name=”mobile.permission.PROVIDER”,那么在其他应用使用该provider时需要加上权限
android:readPermission属性:如果注册provider时使用了该属性,那么其他应用程序通ContentProvider的query()方法查询数据时,必须加上该权限。
android:writePermission属性:如果在注册provider时使用该属性,那么其他应用程序通过ContentProvider的增、删、改这几个方法操作数据时,必须加上权限。
(注意:在注册provider时,为其指定自定义权限。为了让自定义权限生效,首先单机清单文件中permission标签页的Add标签。)
Uri
在ContentProvider的几个抽象方法中,其中有一个参数Uri uri,它代表了数据的操作方法。
Uri时由scheme,authorites,path三部分组成。
示例:content://(scheme)cn.itcast.db.personprovider(authorities)/person(path)
shcme部分content://是一个标准前缀,表明数据被内容提供者所控制,不会被修改。
authorities部分cn.itcast.db.personprovider是在清单文件中指定的android:authorities属性值,该值必须唯一,表示当前的内容提供者。
path部分/person代表资源,当访问者需要不同数据时,这个部分是动态改变的。
访问内容提供者
ContentResolver的基本用法:
通过ContentProvider暴露自己的数据,通过ContentResoler对应用程序暴露的数据进行操作。在使用ContentProvider暴露数据时提供相应的操作Uri,因此在访问现有的ContentProvider时要指定相应的Uri,然后通过ContentResolver对象实现。
//获取相应操作的Uri
Uri uri=Uri.parse("content://cn.itcast.db.personprovider/person");
//获取到ContentReolve对象
ContentResolver resolve=context.getContentResolver(0;
//通过ContentResolver对象查询数据
Cursor cursor=resolver.query(uri,new String []{"address","date","type","body"},null,null,null);
while(Cursor.moveToNext()){
String address=cursor.getString(0);
long date=cursor.getlong(1);
int type=cursor.getInt(2);
String body=cursor.getString(3);
}
cursor.close();
内容观察者
用来观察指定Uri所代表的的数据。当ContentObserver观察到指定Uri所代表的数据。当ContentObserver观察到指定Uri代表的数据发生变化时,就会触发ContentObserver的onChange()方法。此时在onChange()方法里用ContentResolver可以查到变化的数据。
public void ContentObserver(Handle handle)
//ContentObsever的派生类都需要调用该构造方法。参数可以是主线程Handle,也可以是任何Handle对象
public void onChange(boolean selfChange)
//当观察到的Uri代表的数据发生变化时,会触发该方法
如果使用Contentobsever观察数据变化,就必须在ContentProvider中的delete(),insert(),update()方法中调用ContentResolver的notifyChange()方法。
//添加数据
public Uri insert(Uri uri,ContentValues values){
if(matcher.math(uri)==INSERT){//匹配Uri路径
//匹配成功,返回查询结果
SQLiteDatabase db=helper.getWritableDatabase();
db.insert("person",null,values);
getContext().getContentResolver().notifyChange(PersonDao.messageuri,null);
}else{//匹配成功
throw new IllegalArgumentException("路径不匹配,不能执行插入操作");
}
return null;
网络存储
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));
HttpClient是开源组织Apache提供的Java请求网络框架,其最早是为了方便Java服务器开发而诞生的,是对JDK中的HttpUrlConnection各API进行了封装和简化,提高了性能并且降低了调用API的繁琐,Android因此也引进了这个联网框架,我们再不需要导入任何jar或者类库就可以直接使用,值得注意的是Android官方已经宣布不建议使用HttpClient了。
HttpClient发送GET请求
1、 创建HttpClient对象
2、创建HttpGet对象,指定请求地址(带参数)
3、使用HttpClient的execute(),方法执行HttpGet请求,得到HttpResponse对象
4、调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码
5、调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据
public static String loginByHttpClientGet(String username, String password) {
String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=
+ username + &password= + password;
HttpClient client = new DefaultHttpClient(); // 开启网络访问客户端
HttpGet httpGet = new HttpGet(path); // 包装一个GET请求
try {
HttpResponse response = client.execute(httpGet); // 客户端执行请求
int code = response.getStatusLine().getStatusCode(); // 获取响应码
if (code == 200) {
InputStream is = response.getEntity().getContent(); // 获取实体内容
String result = StreamTools.streamToString(is); // 字节流转字符串
return result;
} else {
return 网络访问失败;
}
} catch (Exception e) {
e.printStackTrace();
return 网络访问失败;
}
}
HttpClient发送POST请求
1,创建HttpClient对象
2,创建HttpPost对象,指定请求地址
3,创建List,用来装载参数
4,调用HttpPost对象的setEntity()方法,装入一个UrlEncodedFormEntity对象,携带之前封装好的参数
5,使用HttpClient的execute()方法执行HttpPost请求,得到HttpResponse对象
6, 调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码
7, 调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据
public static String loginByHttpClientPOST(String username, String password) {
String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
try {
HttpClient client = new DefaultHttpClient(); // 建立一个客户端
HttpPost httpPost = new HttpPost(path); // 包装POST请求
// 设置发送的实体参数
List parameters = new ArrayList();
parameters.add(new BasicNameValuePair(username, username));
parameters.add(new BasicNameValuePair(password, password));
httpPost.setEntity(new UrlEncodedFormEntity(parameters, UTF-8));
HttpResponse response = client.execute(httpPost); // 执行POST请求
int code = response.getStatusLine().getStatusCode();
if (code == 200) {
InputStream is = response.getEntity().getContent();
String result = StreamTools.streamToString(is);
return result;
} else {
return 网络访问失败;
}
} catch (Exception e) {
e.printStackTrace();
return 访问网络失败;
}
}
参考:
Android开发请求网络方式详解。