欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

5种Android数据存储方式汇总

程序员文章站 2024-02-25 18:47:39
本文介绍android中的5种数据存储方式。 数据存储在开发中是使用最频繁的,在这里主要介绍android平台中实现数据存储的5种方式,分别是: 1 使用shar...

本文介绍android中的5种数据存储方式。

数据存储在开发中是使用最频繁的,在这里主要介绍android平台中实现数据存储的5种方式,分别是:

1 使用sharedpreferences存储数据
2 文件存储数据
3 sqlite数据库存储数据
4 使用contentprovider存储数据
5 网络存储数据

下面将为大家一一详细介绍。

第一种:使用sharedpreferences存储数据
sharedpreferences是android平台上一个轻量级的存储类,主要是保存一些常用的配置比如窗口状态,一般在activity中 重载窗口状态onsaveinstancestate保存一般使用sharedpreferences完成,它提供了android平台常规的long长 整形、int整形、string字符串型的保存。

它是什么样的处理方式呢? sharedpreferences类似过去windows系统上的ini配置文件,但是它分为多种权限,可以全局共享访问,android123提示最终是以xml方式来保存,整体效率来看不是特别的高,对于常规的轻量级而言比sqlite要好不少,如果真的存储量不大可以考虑自己定义文件格式。xml 处理时dalvik会通过自带底层的本地xml parser解析,比如xmlpull方式,这样对于内存资源占用比较好。

它的本质是基于xml文件存储key-value键值对数据,通常用来存储一些简单的配置信息。
其存储位置在/data/data/< >/shared_prefs目录下。
sharedpreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过editor对象实现。

实现sharedpreferences存储的步骤如下:
step1、根据context获取sharedpreferences对象
step2、利用edit()方法获取editor对象。
step3、通过editor对象存储key-value键值对数据。
step4、通过commit()方法提交数据。

下面是示例代码:

public class mainactivity extends activity {  
 @override
   public void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.main);

    //获取sharedpreferences对象
    context ctx = mainactivity.this;    
    sharedpreferences sp = ctx.getsharedpreferences("sp", mode_private);
    //存入数据
    editor editor = sp.edit();
    editor.putstring("string_key", "string");
    editor.putint("int_key", 0);
    editor.putboolean("boolean_key", true);
    editor.commit();

    //返回string_key的值
    log.d("sp", sp.getstring("string_key", "none"));
    //如果not_exist不存在,则返回值为"none"
    log.d("sp", sp.getstring("not_exist", "none"));
   }

} 

这段代码执行过后,即在/data/data/com.test/shared_prefs目录下生成了一个sp.xml文件,一个应用可以创建多个这样的xml文件。

sharedpreferences对象与sqlite数据库相比,免去了创建数据库,创建表,写sql语句等诸多操作,相对而言更加方便,简洁。但是sharedpreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和string五种简单的数据类型,比如其无法进行条件查询等。所以不论sharedpreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如sqlite数据库这样的其他数据存储方式。

第二种:文件存储数据
关于文件存储,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//files目录,如: /data/data/cn.itcast.action/files/itcast.txt ,通过点击eclipse菜单“window”-“show view”-“other”,在对话窗口中展开android文件夹,选择下面的file explorer视图,然后在file explorer视图中展开/data/data//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//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//cache目录 getfilesdir()方法用于获取/data/data//files目录。

把文件存入sdcard:
使用activity的openfileoutput()方法保存文件,文件是存放在手机空间上,一般手机的存储空间不是很大,存放些小文件还行,如果要存放像视频这样的大文件,是不可行的。对于像视频这样的大文件,我们可以把它存放在sdcard。
sdcard是干什么的?你可以把它看作是移动硬盘或u盘。 在模拟器中使用sdcard,你需要先创建一张sdcard卡(当然不是真的sdcard,只是镜像文件)。

创建sdcard可以在eclipse创建模拟器时随同创建,也可以使用dos命令进行创建,如下: 在dos窗口中进入android sdk安装路径的tools目录,输入以下命令创建一张容量为2g的sdcard,文件后缀可以随便取,建议使用.img: mksdcard 2048m d:\androidtool\sdcard.img 在程序中访问sdcard,你需要申请访问sdcard的权限。

在androidmanifest.xml中加入访问sdcard的权限如下:

 <!-- 在sdcard中创建与删除文件权限 -->
  <uses-permission android:name="android.permission.mount_unmount_filesystems"/>

  <!-- 往sdcard写入数据权限 -->
  <uses-permission android:name="android.permission.write_external_storage"/> 

要往sdcard存放文件,程序必须先判断手机是否装有sdcard,并且可以进行读写。
注意:访问sdcard必须在androidmanifest.xml中加入访问sdcard的权限。

 if(environment.getexternalstoragestate().equals(environment.media_mounted)){ 
file sdcarddir = environment.getexternalstoragedirectory();//获取sdcard目录     

file savefile = new file(sdcarddir, “a.txt”);
    fileoutputstream outstream = new fileoutputstream(savefile);
    outstream.write("test".getbytes());
    outstream.close();
}

​environment.getexternalstoragestate()方法用于获取sdcard的状态,如果手机装有sdcard,并且可以进行读写,那么方法返回的状态等于environment.media_mounted。
environment.getexternalstoragedirectory()方法用于获取sdcard的目录,当然要获取sdcard的目录,你也可以这样写:

file sdcarddir = new file("/sdcard"); //获取sdcard目录
file savefile = new file(sdcarddir, "itcast.txt");
//上面两句代码可以合成一句:
file savefile = new file("/sdcard/a.txt");
fileoutputstream outstream = new fileoutputstream(savefile);
outstream.write("test".getbytes());
outstream.close();

第三种:sqlite数据库存储数据

sqlite是轻量级嵌入式数据库引擎,它支持 sql 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。许多开源项目((mozilla, php, python)都使用了 sqlite.sqlite 由以下几个组件组成:sql 编译器、内核、后端以及附件。sqlite 通过利用虚拟机和虚拟数据库引擎(vdbe),使调试、修改和扩展 sqlite 的内核变得更加方便。

特点:

面向资源有限的设备,

没有服务器进程,

所有数据存放在同一文件中跨平台,

可*复制。

sqlite 内部结构:

​ sqlite 基本上符合 sql-92 标准,和其他的主要 sql 数据库没什么区别。它的优点就是高效,android 运行时环境包含了完整的 sqlite。

sqlite 和其他数据库最大的不同就是对数据类型的支持,创建一个表时,可以在 create table 语句中指定某列的数据类型,但是你可以把任何数据类型放入任何列中。当某个值插入数据库时,sqlite 将检查它的类型。如果该类型与关联的列不匹配,则 sqlite 会尝试将该值转换成该列的类型。如果不能转换,则该值将作为其本身具有的类型存储。比如可以把一个字符串(string)放入 integer 列。sqlite 称这为“弱类型”(manifest typing.)。 此外,sqlite 不支持一些标准的 sql 功能,特别是外键约束(foreign key constrains),嵌套 transcaction 和 right outer join 和 full outer join, 还有一些 alter table 功能。 除了上述功能外,sqlite 是一个完整的 sql 系统,拥有完整的触发器,交易等等。

android 集成了 sqlite 数据库 android 在运行时(run-time)集成了 sqlite,所以每个 android 应用程序都可以使用 sqlite 数据库。

对于熟悉 sql 的开发人员来时,在 android 开发中使用 sqlite 相当简单。但是,由于 jdbc 会消耗太多的系统资源,所以 jdbc 对于手机这种内存受限设备来说并不合适。因此,android 提供了一些新的 api 来使用 sqlite 数据库,android 开发中,程序员需要学使用这些 api。

数据库存储在 data/< 项目文件夹 >/databases/ 下。 android 开发中使用 sqlite 数据库 activites 可以通过 content provider 或者 service 访问一个数据库。

下面会详细讲解如果创建数据库,添加数据和查询数据库。 创建数据库 android 不自动提供数据库。在 android 应用程序中使用 sqlite,必须自己创建数据库,然后创建表、索引,填充数据。

android 提供了 sqliteopenhelper 帮助你创建一个数据库,你只要继承 sqliteopenhelper 类,就可以轻松的创建数据库。sqliteopenhelper 类根据开发应用程序的需要,封装了创建和更新数据库使用的逻辑。

sqliteopenhelper 的子类,至少需要实现三个方法:

1 构造函数调用父类 sqliteopenhelper 的构造函数。这个方法需要四个参数:上下文环境(例如,一个 activity),数据库名字,一个可选的游标工厂(通常是 null),一个代表你正在使用的数据库模型版本的整数。

2 oncreate()方法它需要一个 sqlitedatabase 对象作为参数,根据需要对这个对象填充表和初始化数据。

3 onupgrage() 方法,它需要三个参数,一个 sqlitedatabase 对象,一个旧的版本号和一个新的版本号,这样你就可以清楚如何把一个数据库从旧的模型转变到新的模型。

下面示例代码展示了如何继承 sqliteopenhelper 创建数据库:

public class databasehelper extends sqliteopenhelper {  
 databasehelper(context context, string name, cursorfactory cursorfactory, int version) 
 {   
  super(context, name, cursorfactory, version);   
   }   

   @override  
   public void oncreate(sqlitedatabase db) {   
     // todo 创建数据库后,对数据库的操作   
   }   

   @override  
 public void onupgrade(sqlitedatabase db, int oldversion, int newversion) {   
     // todo 更改数据库版本的操作   
   }   

 @override  
 public void onopen(sqlitedatabase db) {   
     super.onopen(db);    
     // todo 每次成功打开数据库后首先被执行   
   }   
 }  

接下来讨论具体如何创建表、插入数据、删除表等等。调用 getreadabledatabase() 或 getwriteabledatabase() 方法,你可以得到 sqlitedatabase 实例,具体调用那个方法,取决于你是否需要改变数据库的内容:

 db=(new databasehelper(getcontext())).getwritabledatabase();
    return (db == null) ? false : true; 

上面这段代码会返回一个 sqlitedatabase 类的实例,使用这个对象,你就可以查询或者修改数据库。 当你完成了对数据库的操作(例如你的 activity 已经关闭),需要调用 sqlitedatabase 的 close() 方法来释放掉数据库连接。 创建表和索引 为了创建表和索引,需要调用 sqlitedatabase 的 execsql() 方法来执行 ddl 语句。如果没有异常,这个方法没有返回值。

例如,你可以执行如下代码:

db.execsql("create table mytable (_id integer primary key autoincrement, title text, value real);"); 

这条语句会创建一个名为 mytable 的表,表有一个列名为 _id,并且是主键,这列的值是会自动增长的整数(例如,当你插入一行时,sqlite 会给这列自动赋值),另外还有两列:title( 字符 ) 和 value( 浮点数 )。 sqlite 会自动为主键列创建索引。 通常情况下,第一次创建数据库时创建了表和索引。

如果你不需要改变表的 schema,不需要删除表和索引 . 删除表和索引,需要使用 execsql() 方法调用 drop index 和 drop table 语句。 给表添加数据 上面的代码,已经创建了数据库和表,现在需要给表添加数据。有两种方法可以给表添加数据。

像上面创建表一样,你可以使用 execsql() 方法执行 insert, update, delete 等语句来更新表的数据。execsql() 方法适用于所有不返回结果的 sql 语句。

例如: db.execsql(“insert into widgets (name, inventory)”+ “values (‘sprocket', 5)”);

另一种方法是使用 sqlitedatabase 对象的 insert(), update(), delete() 方法。这些方法把 sql 语句的一部分作为参数。

示例如下:

contentvalues cv=new contentvalues();
cv.put(constants.title, "example title");
cv.put(constants.value, sensormanager.gravity_death_star_i);
db.insert("mytable", getnullcolumnhack(), cv);

update()方法有四个参数,分别是表名,表示列名和值的 contentvalues 对象,可选的 where 条件和可选的填充 where 语句的字符串,这些字符串会替换 where 条件中的“?”标记。

update() 根据条件,更新指定列的值,所以用 execsql() 方法可以达到同样的目的。 where 条件和其参数和用过的其他 sql apis 类似。

例如:

string[] parms=new string[] {“this is a string”};
db.update(“widgets”, replacements, “name=?”, parms); 

delete() 方法的使用和 update() 类似,使用表名,可选的 where 条件和相应的填充 where 条件的字符串。 查询数据库 类似 insert, update, delete,有两种方法使用 select 从 sqlite 数据库检索数据。

1.使用 rawquery() 直接调用 select 语句; 使用 query() 方法构建一个查询。

raw queries 正如 api 名字,rawquery() 是最简单的解决方法。通过这个方法你就可以调用 sql select 语句。

例如: cursor c=db.rawquery( “select name from sqlite_master where type='table' and name='mytable'”, null);

在上面例子中,我们查询 sqlite 系统表(sqlite_master)检查 table 表是否存在。返回值是一个 cursor 对象,这个对象的方法可以迭代查询结果。 如果查询是动态的,使用这个方法就会非常复杂。

例如,当你需要查询的列在程序编译的时候不能确定,这时候使用 query() 方法会方便很多。

regular queries query() 方法用 select 语句段构建查询。select 语句内容作为 query() 方法的参数,比如:要查询的表名,要获取的字段名,where 条件,包含可选的位置参数,去替代 where 条件中位置参数的值,group 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(), 和 isafterlast() 方法遍历所有记录;

通过 getcolumnnames() 得到字段名;

通过 getcolumnindex() 转换成字段号;

通过 getstring(),getint() 等方法得到给定字段当前记录的值;

通过 requery() 方法重新执行查询得到游标;

通过 close() 方法释放游标资源;

例如,下面代码遍历 mytable 表:

cursor result=db.rawquery(“select id, name, inventory from mytable”); 
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();

在android 中使用 sqlite 数据库管理工具 在其他数据库上作开发,一般都使用工具来检查和处理数据库的内容,而不是仅仅使用数据库的 api。

使用 android 模拟器,有两种可供选择的方法来管理数据库。

首先,模拟器绑定了 sqlite3 控制台程序,可以使用 adb shell 命令来调用他。只要你进入了模拟器的 shell,在数据库的路径执行 sqlite3 命令就可以了。

数据库文件一般存放在: /data/data/your.app.package/databases/your-db-name 如果你喜欢使用更友好的工具,你可以把数据库拷贝到你的开发机上,使用 sqlite-aware 客户端来操作它。这样的话,你在一个数据库的拷贝上操作,如果你想要你的修改能反映到设备上,你需要把数据库备份回去。

把数据库从设备上考出来,你可以使用 adb pull 命令(或者在 ide 上做相应操作)。

存储一个修改过的数据库到设备上,使用 adb push 命令。 一个最方便的 sqlite 客户端是 firefox sqlite manager 扩展,它可以跨所有平台使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。