Android中的四大数据存储方式解析

来源:互联网 发布:中兴软件开发技术面 编辑:程序博客网 时间:2024/06/06 04:08

--使用SharedPreferences存储数据;

--文件存储数据;

--SQLite数据库存储数据;

--使用ContentProvider存储数据;

一:使用SharedPreferences存储数据

首先说明SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的一种机制,
例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:

void WriteSharedPreferences(String strName,String strPassword){
  SharedPreferences   user = getSharedPreferences(“user_info”,0);
  uer.edit();
  user.putString(“NAME”, strName);
  user.putString(“PASSWORD” ,strPassword);
  user.commit();
}
void ReadSharedPreferences(){
  String strName,strPassword;
  SharedPreferences   user = getSharedPreferences(“user_info”,0);
  strName = user.getString(“NAME”,””);
  strPassword = user getString(“PASSWORD”,””);
}

数据读取与写入的方法都非常简单,只是在写入的时候有些区别:
先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。
实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的File Explorer中的/data/data/<package name>/shares_prefs下。
以上面的数据存储结果为例,打开后可以看到一个user_info.xml的文件,打开后可以看到:

<?xml version=”1.0″ encoding=”UTF-8″?>
<map>
  <string name=”NAME”>moandroid</string>
  <string name=” PASSWORD”>SharedPreferences</string>
</map>
使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用。

二:文件存储数据
文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,
提供了openFileInput()和openFileOutput()方法来读取设备上的文件。
public void writeData(View v)throws Exception{
  OutputStream out=
  openFileOutput("a1.txt",
  Context.MODE_PRIVATE);//Context.MODE_APPEND;(私有,追加)
  out.write("HelloWorld".getBytes());
  out.close();
 }
public void readData(View v)throws Exception{
  InputStream in=
  openFileInput("a1.txt");//context
  byte buf[]=new byte[64];
  int len=in.read(buf);
  String s=new String(buf,0,len);
  Toast.makeText(this,s, 1).show();
  in.close();
 }


第三种:SQLite存储数据

SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。现在的主流移动设备像Android、iPhone等都使用

SQLite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到SQLite来存储我们大量的数据,所以我们就需要掌握移动设备上

的SQLite开发技巧

SQLiteDatabase类为我们提供了很多种方法,上面的代码中基本上囊括了大部分的数据库操作;对于添加、更新和删除来说,我们都可以使用

1 db.executeSQL(String sql); 
2 db.executeSQL(String sql, Object[] bindArgs);//sql语句中使用占位符,然后第二个参数是实际的参数集 除了统一的形式之外,他们还有各自

的操作方法:

1 db.insert(String table, String nullColumnHack, ContentValues values); 
2 db.update(String table, Contentvalues values, String whereClause, String whereArgs); 
3 db.delete(String table, String whereClause, String whereArgs);以上三个方法的第一个参数都是表示要操作的表名;insert中的第二个参数表

示如果插入的数据每一列都为空的话,需要指定此行中某一列的名称,系统将此列设置为NULL,不至于出现错误;insert中的第三个参数是

ContentValues类型的变量,是键值对组成的Map,key代表列名,value代表该列要插入的值;update的第二个参数也很类似,只不过它是更新该字段

key为最新的value值,第三个参数whereClause表示WHERE表达式,比如“age > ? and age < ?”等,最后的whereArgs参数是占位符的实际参数值;

delete方法的参数也是一样

数据的添加

1.使用insert方法


1 ContentValues cv = new ContentValues();//实例化一个ContentValues用来装载待插入的数据
2 cv.put("title","you are beautiful");//添加title
3 cv.put("weather","sun"); //添加weather
4 cv.put("context","xxxx"); //添加context
5 String publish = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
6                         .format(new Date());
7 cv.put("publish ",publish); //添加publish
8 db.insert("diary",null,cv);//执行插入操作2.使用execSQL方式来实现

String sql = "insert into user(username,password) values ('Jack Johnson','iLovePopMuisc');//插入操作的SQL语句
db.execSQL(sql);//执行SQL语句数据的删除

2.delete同样有2种方式可以实现

String whereClause = "username=?";//删除的条件
String[] whereArgs = {"Jack Johnson"};//删除的条件参数
db.delete("user",whereClause,whereArgs);//执行删除使用execSQL方式的实现

String sql = "delete from user where username='Jack Johnson'";//删除操作的SQL语句
db.execSQL(sql);//执行删除操作数据修改

3.update同上,仍是2种方式

ContentValues cv = new ContentValues();//实例化ContentValues
cv.put("password","iHatePopMusic");//添加要更改的字段及内容
String whereClause = "username=?";//修改条件
String[] whereArgs = {"Jack Johnson"};//修改条件的参数
db.update("user",cv,whereClause,whereArgs);//执行修改使用execSQL方式的实现

String sql = "update user set password = 'iHatePopMusic' where username='Jack Johnson'";//修改的SQL语句
db.execSQL(sql);//执行修改数据查询

4.query查询操作相对于上面的几种操作要复杂些,因为我们经常要面对着各种各样的查询条件,所以系统也考虑到这种复杂性,为我们提供了较为丰

富的查询形式:


1 db.rawQuery(String sql, String[] selectionArgs); 
2 db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy);

 
3 db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy,

String limit); 
4 db.query(String distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having,

String orderBy, String limit);  上面几种都是常用的查询方法,第一种最为简单,将所有的SQL语句都组织到一个字符串中,使用占位符代替实际

参数,selectionArgs就是占位符实际参数集;

各参数说明:

•table:表名称
•colums:表示要查询的列所有名称集
•selection:表示WHERE之后的条件语句,可以使用占位符
•selectionArgs:条件语句的参数数组
•groupBy:指定分组的列名
•having:指定分组条件,配合groupBy使用
•orderBy:y指定排序的列名
•limit:指定分页参数
•distinct:指定“true”或“false”表示要不要过滤重复值
•Cursor:返回值,相当于结果集ResultSet
最后,他们同时返回一个Cursor对象,代表数据集的游标,有点类似于JavaSE中的ResultSet。下面是Cursor对象的常用方法:

 1 c.move(int offset); //以当前位置为参考,移动到指定行 
 2 c.moveToFirst();    //移动到第一行 
 3 c.moveToLast();     //移动到最后一行 
 4 c.moveToPosition(int position); //移动到指定行 
 5 c.moveToPrevious(); //移动到前一行 
 6 c.moveToNext();     //移动到下一行 
 7 c.isFirst();        //是否指向第一条 
 8 c.isLast();     //是否指向最后一条 
 9 c.isBeforeFirst();  //是否指向第一条之前 
10 c.isAfterLast();    //是否指向最后一条之后 
11 c.isNull(int columnIndex);  //指定列是否为空(列基数为0) 
12 c.isClosed();       //游标是否已关闭 
13 c.getCount();       //总数据项数 
14 c.getPosition();    //返回当前游标所指向的行数 
15 c.getColumnIndex(String columnName);//返回某列名对应的列索引值 
16 c.getString(int columnIndex);   //返回当前行指定列的值 实现代码

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

通过rawQuery实现的带参数查询


Cursor result=db.rawQuery("SELECT ID, name, inventory FROM mytable");
//Cursor c = db.rawQuery("s name, inventory FROM mytable where ID=?",new Stirng[]{"123456"});    
result.moveToFirst();
while (!result.isAfterLast()) {
    int id=result.getInt(0);
    String name=result.getString(1);
    int inventory=result.getInt(2);
    // do something useful with these
    result.moveToNext();
 }
 result.close();

在上面的代码示例中,已经用到了这几个常用方法中的一些,关于更多的信息,大家可以参考官方文档中的说明。

最后当我们完成了对数据库的操作后,记得调用SQLiteDatabase的close()方法释放数据库连接,否则容易出现SQLiteException。

上面就是SQLite的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自SQLiteOpenHelper类的数据库操作类,然后

以这个类为基础,再封装我们的业务逻辑方法。

 

四:ContentProvider

1、ContentProvider简介
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据

,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需

要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。?

2、Uri类简介
Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider ,2.对ContentProvider中的什么数据进行操作,一个Uri由以下

几部分组成:

1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。
2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:

要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
要操作contact表中id为10的记录的name字段, contact/10/name
要操作contact表中的所有记录,可以构建这样的路径:/contact?
要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")

3、UriMatcher、ContentUrist和ContentResolver简介

因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher

和ContentUris 。掌握它们的使用,会便于我们的开发工作。

UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配 content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);//#号为通配符

2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入

的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。
ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)用于为路径加上ID部分
parseId(uri)方法用于从路径中获取ID部分

ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取

ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作

数据。
 
五:总结说明
以上5中存储方式,在以后的开发过程中,根据设计目标、性能需求、空间需求等找到合适的数据存储方式。
Android 中的数据存储都是私有的,其他应用程序都是无法访问的,除非通过ContentResolver获取其他程序共享的数据。
采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。
而使用ContentProvider共享数据的好处是统一了数据访问方式。

 

0 0
原创粉丝点击