1、middleware technology and applicationAndroid四种存储方式四种存储方式宁夏大学数学计算机学院二零一五年作为一个完整的应用程序,数据存储操作是必不可少的。Android系统一共提供了四种数据存储方式。分别是:SharePreference、SQLite、Content Provider和File。由于Android系统中,数据基本都是私有的的,都是存放于“data/data/程序包名”目录下,所以要实现数据共享,正确方式是使用Content Provider。Android四种存储方式四种存储方式middleware technology and app
2、lication一、一、File存储方式存储方式File:即常说的文件(I/O)存储方法,常用存储大数量的数据,但是缺点是更新数据将是一件困难的事情。下面实现:在本地data文件下使用自己生成的文件处理数据的新建储存、读取、删除。File基本概念基本概念1.保存文件内容:通过Context.openFileOutput获取输出流,参数分别为文件名和存储模式。2.读取文件内容:通过Context.openFileInput获取输入流,参数为文件名。3.删除文件:Context.deleteFile删除指定的文件,参数为将要删除的文件的名称。4.获取文件名列表:通过Context.fileList
3、获取files目录下的所有文件名数组。*获取文件路径的方法:绝对路径:/data/data/files/filenameContext:Context.getFilesDir()可以获取到/data/data/filesFile方式实现的基本操作方式实现的基本操作1.Context.MODE_PRIVATE 为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下写入的内容会覆盖原文件的内容。2.Context.MODE_APPEND 检查文件是否存在,存在就往文件追加内容,否则就创建新文件。3.MODE_WORLD_READABLE 表示当前文件可以被其他应用读取。4.MODE_
4、WORLD_WRITEABLE 表示当前文件可以被其他应用写入。在使用模式时,可以用“+”来选择多种模式,如:openFileOutput(FILENAME,Context.MODE_PRIVATE+MODE_WORLD_READABLE);四种文件保存的模式。private void write()String nameage=“名字:”+name.getText().toString().trim()+“年龄:+age.getText().toString();try os=this.openFileOutput(SHARED_MAIN_XML,MODE_PRIVATE);/*把字符串转换
5、成字节数组,写入文件中*/os.write(nameage.getBytes();catch(FileNotFoundException e)e.printStackTrace();catch(IOException e)e.printStackTrace();finally try/*关闭文件输出流*/os.close();catch(IOException e)e.printStackTrace();写:private String read()String nameage=“;/打开文件输入流,try is=this.openFileInput(SHARED_MAIN_XML);/*初始
6、化字节数组*/b=new byte1024;/*从文件输入流中读取内容到字节数组中,返回内容长度*/int length=is.read(b);/*把字节数组转换成字符串*/nameage=new String(b);catch(FileNotFoundException e)e.printStackTrace();catch(IOException e)e.printStackTrace();return nameage;读:middleware technology and application二、二、SQLite存储方式存储方式SQLite基本概念基本概念SQLite是一个轻量级的数据
7、库,支持基本SQL语法,是常被采用的一种数据存储方式。Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API。SQLite是一种转为嵌入式设备设计的轻型数据库,其只有五种数据类型,分别是:NULL:空值 INTEGER:整数REAL:浮点数 TEXT:字符串BLOB:大数据在SQLite中,并没有专门设计BOOLEAN和DATE类型,因为BOOLEAN型可以用INTEGER的0和1代替true和false,而DATE类型则可以拥有特定格式的TEXT、REAL和INTEGER的值来代替显示,为了能方便的操作DATE类型,SQLite提供了一组函数,详
8、见:http:/www.sqlite.org/lang_datefunc.html。关于关于SQLite在Android系统中提供了android.database.sqlite包,用于进行SQLite数据库的增、删、改、查工作。其主要方法如下:beginTransaction():开始一个事务。close():关闭连接,释放资源。endTransaction():结束一个事务。execSQL(String sql):执行给定SQL语句。delete(String table,String whereClause,String whereArgs):根据给定条件,删除符合条件的记录。SQLit
9、e中的中的 APIinsert(String table,String nullColumnHack,ContentValues values):根据给定条件,插入一条记录。openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory):根据给定条件连接数据库,如果此数据库不存在,则创建。query(String table,String columns,String selection,String selectionArgs,String groupBy,String having,String orderBy)
10、:执行查询。SQLite中的中的 APIrawQuery(String sql,String selectionArgs):根据给定SQL,执行查询。update(String table,ContentValues values,String whereClause,String whereArgs):根据给定条件,修改符合条件的记录。除了上诉主要方法外,Android还提供了诸多实用的方法,总之一句话:其实Android访问数据库是一件很方便的事儿。SQLite中的中的 API封装一个类去继承SQLiteOpenHelper 在构造函数中传入数据库名称与数据库版本号。数据库被创建的时候会调
11、用onCreate(SQLiteDatabase db)方法。数据库版本号发生改变的时候会调用onUpgrade(SQLiteDatabase db,int oldVersion,intnewVersion)方法。创建与删除数据库创建与删除数据库调用SQLiteOpenHelper 的getReadableDatabase()方法去创建数据库,如果数据库不存在则创建并且返回SQLiteDatabase对象,如果数据库存在则不创建只返回SQLiteDatabase对象。调用 deleteDatabase(DATABASE_NAME)方法 传入数据库名称则可删除数据库。创建与删除数据库创建与删除数
12、据库publicclassUserService privateDatabaseHelperhelper;publicUserService(Contextcontext,Stringname,intversion)helper=newDatabaseHelper(context,name,version);publicUserService(Contextcontext,Stringname)helper=newDatabaseHelper(context,name);下面是个简单的例子,用来实现增删改:下面是个简单的例子,用来实现增删改:插入数据插入数据publicvoidinsert(U
13、serDaouser)/插入数据SQLiteDatabasesdb=helper.getWritableDatabase();ContentValuesvalues=newContentValues();values.put(username,user.getUsername();values.put(password,user.getPassword();sdb.insert(user,name,values);sdb.close();publicvoiddelete(intid)/删除数据SQLiteDatabasesdb=helper.getWritableDatabase();sdb.
14、delete(user,id=?,newStringString.valueOf(id);sdb.close();删除数据删除数据publicvoidupdate(UserDaouser,intid)/更新数据SQLiteDatabasesdb=helper.getWritableDatabase();ContentValuesvalues=newContentValues();values.put(username,user.getUsername();values.put(password,user.getPassword();sdb.update(user,values,id=?,new
15、StringString.valueOf(id);sdb.close();更新数据更新数据publicCursorselect()/查询所有数据SQLiteDatabasesdb=helper.getWritableDatabase();returnsdb.query(user,newStringidas_id,username,password,null,null,null,null,null);查询所有数据publicUserDaofind(intid)/按id查询数据UserDaouser=null;SQLiteDatabasesdb=helper.getWritableDatabase
16、();Cursorcursor=sdb.query(user,newStringid,username,password,id=?,newStringString.valueOf(id),null,null,null);if(cursor.moveToFirst()user=newUserDao();user.setId(cursor.getInt(0);user.setUsername(cursor.getString(1);user.setPassword(cursor.getString(2);cursor.close();sdb.close();returnuser;按id查询数据插入
17、数据:通过insert(String table,StringnullColumnHack,ContentValues values)方法插入数据,其中参数含义分别为:table:目标表名nullColumnHack:指定表中的某列列名。因为在SQLite中,不允许不允许插入所有列均为null的记录,因此初始值有值为空时,此列需显式赋予nullvalues:ContentValues对象,类似于java中的Map。以键值对的方式保存数据。插入数据:插入数据:修改数据:update(String table,ContentValues values,String whereClause,Stri
18、ng whereArgs)方法用于修改数据,其四个参数的具体含义如下:table:目标表名values:要被修改成为的新值whereClause:where子句,除去where关键字剩下的部分,其中可带?占位符。如没有子句,则为null。whereArgs:用于替代whereClause参数中?占位符的参数。如不需传入参数,则为null。修改数据:修改数据:查询数据:query()方法用SELECT 语句段构建查询。SELECT 语句内容作为 query()方法的参数,比如:要查询的表名,要获取的字段名,WHERE 条件,包含可选的位置参数,去替代 WHERE 条件中位置参数的值,GROUP
19、BY 条件,HAVING 条件。除了表名,其他参数可以是 null。所以,以前的代码段可以可写成:String columns=ID,inventory;String parms=snicklefritz;Cursor result=db.query(widgets,columns,name=?,parms,null,null,null);查询数据:查询数据:不管你如何执行查询,都会返回一个 Cursor,这是 Android 的 SQLite 数据库游标,使用游标,你可以:通过使用 getCount()方法得到结果集中有多少记录;通过 moveToFirst(),moveToNext(),和
20、 isAfterLast()方法遍历所有记录;通过 getColumnNames()得到字段名;通过 getColumnIndex()转换成字段号;通过 getString(),getInt()等方法得到给定字段当前记录的值;通过 requery()方法重新执行查询得到游标;通过 close()方法释放游标资源;使用游标使用游标删除数据:删除数据也是一件很简单的事,只需要调用delete方法,传入参数即可,delete(String table,String whereClause,String whereArgs)的参数三个参数具体含义如下:table:目标表名whereClause:whe
21、re子句,除去where关键字剩下的部分,其中可带?占位符。如没有子句,则为null。whereArgs:用于替代whereClause参数中?占位符的参数。如不需传入参数,则为null。删除数据:删除数据:middleware technology and application三、三、SharedPreferences存存储方式储方式SharedPreferences是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。其存储位置在/data/data/shared_prefs目录下。SharedPreferences对象本身只
22、能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。SharedPreferences基本概念基本概念一、根据Context获取SharedPreferences对象二、利用edit()方法获取Editor对象。三、通过Editor对象存储key-value键值对数据。四、通过commit()方法提交数据。具体实现代码如下:实现存储,读取,清除,删除实现实现SharedPreferences存储步骤如下:存储步骤如下:privatevoidwrite()/存入数据savename=name.getText().toString().trim();saveage=Integer.v
23、alueOf(age.getText().toString().trim();Editoreditor=mShared.edit();editor.putString(name,savename);editor.putInt(age,saveage);/保证操作的事务完整性mit();存储:privateStringread()/从数据库里读取数据namecontent=mShared.getString(name,数据库里没有存储姓名);agecontent=mShared.getInt(age,0);Stringreading=姓名:+namecontent+n年龄:+agecontent
24、;returnreading;读取:privatevoidclear()/清除内容/*开始清除SharedPreferences中保存的内容*/Editoreditor=mShared.edit();editor.remove(name);editor.remove(age);mit();清除:privatevoiddelete()/删除文件/*删除SharedPreferences文件*/Filefile=newFile(/data/data/cn.csdn.activity+/shared_prefs/+SHARED_MAIN_XML+.xml);if(file.exists()file.
25、delete();Toast.makeText(this,删除成功,Toast.LENGTH_LONG).show();删除:sharedPreferences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。小结小结
26、middleware technology and application四、四、Content Provider存存储方式储方式Content Provider主要内容主要内容1.Content Provider基本概念1.Uri1.ContentProvider的实现方法Content Provider基本概念基本概念1.Content Provider提供为存储和截取数据提供了统一的接口2.每个Content Provider都会对外提供一个公共的URI(包装成Uri对象),如果应用程序有数据需要共享时,就需要使用Content Provider为这些数据定义一个URI,然后其他的应用程
27、序就通过Content Provider传入这个URI来对数据进行操作。3.Android为常见的一些数据提供了Content Provider(包括音频,视频,图片和通讯录等等)Uri是一个通用资源标志符,将其分为A,B,C,D 4个部分:A:无法改变的标准前缀,包括;content:/、tel:/等。当前缀是content:/时,说明通过一个Content Provider控制这些数据B:URI的标识,它通过authorities属性声明,用于定义了是哪个ContentProvider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。例如:con
28、tent:/com.test.data.myproviderC:路径,可以近似的理解为需要操作的数据库中表的名字,如:content:/hx.android.text.myprovider/name中的nameD:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部;URI说明说明ContentProvider是安卓平台中,在不同应用程序之间实现数据共享的一种机制。一个应用程序如果需要让别的程序可以操作自己的数据,即可采用这种机制。并且此种方式忽略了底层的数据存储实现,ContentProvider提供了一种统一的通过Uri实现数据操作的方式。其步骤
29、为:实现实现Content Provider的过程的过程1.在当前应用程序中定义一个ContentProvider。2.在当前应用程序的AndroidManifest.xml中注册此ContentProvider3.其他应用程序通过ContentResolver和Uri来获取此ContentProvider的数据。ContentResolver提供了诸如insert(),delete(),query()和update()之类的方法。用于实现对ContentProvider中数据的存取操作。其步骤为:其步骤为:首先创建继承contentprovider的类。publicclassUserCont
30、entProviderextendsContentProviderprivateDatabaseHelperhelper;privateSQLiteDatabasedb;privatestaticUriMatchermatcher=newUriMatcher(UriMatcher.NO_MATCH);privatestaticfinalintUSERS=1;privatestaticfinalintUSER=2;staticmatcher.addURI(cn.csdn.activity.providers.userprovider,user,USERS);matcher.addURI(cn.c
31、sdn.activity.providers.userprovider,user/#,USER);下面是实现代码:下面是实现代码:publicintdelete(Uriuri,Stringselection,StringselectionArgs)db=helper.getWritableDatabase();intnum=0;switch(matcher.match(uri)caseUSERS:num=db.delete(user,selection,selectionArgs);break;caseUSER:longid=ContentUris.parseId(uri);Stringwhe
32、re=id=+id;if(selection!=null&!.equals(selection)where=where+and+selection;num=db.delete(user,where,selectionArgs);break;default:thrownewIllegalArgumentException(UnknownUri:+uri);returnnum;实现实现delete方法:方法:publicStringgetType(Uriuri)switch(matcher.match(uri)caseUSERS:returnvnd.android.cursor.dir/perso
33、n;caseUSER:returnvnd.android.cursor.item/person;default:thrownewIllegalArgumentException(UnknownUri:+uri);实现实现getType方法:方法:publicUriinsert(Uriuri,ContentValuesvalues)db=helper.getWritableDatabase();longrowid;switch(matcher.match(uri)caseUSERS:/向表中添加新纪录并返回其行号rowid=db.insert(user,id,values);returnCont
34、entUris.withAppendedId(uri,rowid);default:thrownewIllegalArgumentException(UnknowUri:+uri);实现实现Insert方法:方法:publicbooleanonCreate()helper=newDatabaseHelper(this.getContext(),users.db);returntrue;实现实现OnCreate方法:方法:publicCursorquery(Uriuri,Stringprojection,Stringselection,StringselectionArgs,Stringsort
35、Order)db=helper.getReadableDatabase();switch(matcher.match(uri)caseUSERS:returndb.query(user,projection,selection,selectionArgs,null,null,sortOrder);caseUSER:longid=ContentUris.parseId(uri);Stringwhere=id=+id;if(selection!=null&!.equals(selection)where=where+and+selection;returndb.query(user,project
36、ion,where,selectionArgs,null,null,sortOrder);default:thrownewIllegalArgumentException(UnknownUri:+uri);实现实现query方法:方法:publicintupdate(Uriuri,ContentValuesvalues,Stringselection,StringselectionArgs)db=helper.getWritableDatabase();intnum;switch(matcher.match(uri)caseUSERS:num=db.update(user,values,sel
37、ection,selectionArgs);break;caseUSER:longid=ContentUris.parseId(uri);Stringwhere=id=+id;if(selection!=null&!.equals(selection)where=where+and+selection;num=db.update(user,values,selection,selectionArgs);break;default:thrownewIllegalArgumentException(UnknowUri+uri);returnnum;实现实现update方法:方法:需要在中为prov
38、ider进行注册!providerandroid:authorities=cn.csdn.activity.providers.userproviderandroid:name=UserContentProvider配置配置manifest.xml/contentprovider测试publicvoidtestinsert()/插入数据ContentResolverresolver=this.getContext().getContentResolver();Uriinserturi=Uri.parse(content:/cn.csdn.activity.providers.userprovi
39、der/user);ContentValuesvalues=newContentValues();values.put(username,renhiali);values.put(password,123);Uriuri=resolver.insert(inserturi,values);Log.i(TAG,uri.toString();最后写测试类:publicvoidtestdelete()/删除数据ContentResolverresolver=this.getContext().getContentResolver();Urideleteuri=Uri.parse(content:/c
40、n.csdn.activity.providers.userprovider/user/7);intnum=resolver.delete(deleteuri,null,null);Log.i(TAG,num+);删除数据删除数据publicvoidtestupdate()/更新数据ContentResolverresolver=this.getContext().getContentResolver();Uriuri=Uri.parse(content:/cn.csdn.activity.providers.userprovider/user/8);ContentValuesvalues=n
41、ewContentValues();values.put(username,123);resolver.update(uri,values,null,null);更新数据更新数据publicvoidtestquery()/查询数据ContentResolverresolver=this.getContext().getContentResolver();Uriuri=Uri.parse(content:/cn.csdn.activity.providers.userprovider/user/4);Cursorcursor=resolver.query(uri,null,null,null,null);cursor.moveToFirst();Log.i(TAG,cursor.getString(1);cursor.close();查询数据查询数据这种存储方式相比SQLite和SharedPreferences,其复杂性是显而易见的,但是在处处可见“云”的今天,程序间的数据交互需求令ContentProvider存储机制变成必不可少的一部分。总结总结