学习笔记| AS入门(七) 数据存储篇

一个好的开发平台要对数据的存储有良好的支持,而不是仅靠保存在内存中的瞬时数据。本篇主要介绍Android平台实现数据存储的三种方式,分别是:

  • File 文件存储
  • SharedPreferences存储
  • SQLite数据库存储

在分别介绍之前,先要知道以上三种方法使得数据文件都默认存储在哪里,方便后续验证,如图:

另外,关于如何在DDMS里File Explore下打开data文件夹以及导出文件在技能篇有详细说明,本篇不再赘述,验证时将直接展示导出文件内容。

1.File文件存储

在Android中写入和读取文件的方法,和 Java中实现I/O的程序是一样的,Context类中提供了openFileInput()和openFileOutput()方法来打开数据文件里的文件IO流。下面直接通过一个demo学习Android如何通过文件来保存数据。

(1)写入数据

新建布局mylayout.xml,只加入一个EditText用于输入文本内容:

新建MyActivity,在onCreate()获取EditText实例,然后重写onDestory()为了在活动销毁之前将输入的文本内容存储起来。具体方法是:先获取了EditText中输入的文本text,然后openFileOutput()方法将text存储到名为data的文件中并且能够得到一个FileOutputStream 对象,,再借助它构建出一 个OutputStreamWriter对象,接着再使用OutputStreamWriter 构建出一个 BufferedWriter 对象,这样就可以通过BufferedWriter来将文本内容写入到文件中了。

关键方法:

  FileOutputStream fileOutputStream = openFileOutput("data", Context.MODE_PRIVATE);
                bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
                bufferedWriter.write(text);

其中openFileOutput()的第二个参数,表示文件的操作模式,常用的可选值含义见下图:

运行程序,在输入框里输入Hello AS!然后退出程序。

查看DDMS,果然有data文件!导出后内容和输入完全一致,证实了内容确实成功保存到文件了。

(2)读取数据

接下来我们想让程序再次启动时输入框内已经显示刚刚写入的数据。在OnCreate()中用openFileInput()方法指定了要从文件data中读取数据,之后代码和写入是对应的非常好理解。读取到内容之后判断是否为空,若不为空,就set到EditText里,并调用setSelection 方法将输入光标移动到文本的末尾位置以便于继续输入,再弹出一句重新加载成功的提示。

关键方法:

 FileInputStream fileInputStream=openFileInput("data");
            bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
            String line;
            while((line=bufferedReader.readLine())!=null){
                content.append(line);
            }

运行程序,效果如图:

2.SharePreferences存储

SharePreferences是一种轻型的数据存储方式,常用来存储一些简单的配置信息,如int、string、boolean、float和long。它的本质是基于XML文件存储key-value键值对数据。

实现SharedPreferences存储的步骤如下:
(1)调用getSharedPreferences()方法获得SharedPreferences对象,提供两个参数,指定文件名和操作模式。
(2)调用SharedPreference对象的edit()方法获得SharedPreferences.Editor引用对象
(3)调用Edit接口的形如put某某某()方法以键值对形式保存某某某类型的数据
(4)调用Edit接口的commit()方法提交键值对。
一定注意,不用SharedPreferences对象去存储或修改数据,而是通过Editor对象。但获取数据时需要调用SharedPreferences对象的get某某某()方法了。

学习完SharePreferences基本知识点后,通过一个有记住密码功能的demo来巩固一下吧!新建login.xml,这里做一个登陆界面,如下图所示。相信这样的一个页面难不倒你,布局嵌套就能实现了。

在MainActvity的onCreate()里先获取除了TextView的所有控件、实例化SharedPreferences和SharedPreferences.Editor、给两个按钮都注册击事件,代码如下:

再来看看点击事件,当点击cancel时,直接finish()结束当前活动;当点击login时,第一轮判断用户名和密码是否对应(假设只有一个账户),如果不对应就弹出提示登陆不成功,如果对应就提示登陆成功并跳转到另一个页面,在跳转之前要进行第二轮判断以保证数据不丢失,判断CheckBox是否选中,如果未选中就用Edit清除所有数据,如果选中就添加用户名和密码,注意最后一定要commit提交。

下两个图就是跳转页面的布局和活动了。

最后再回到MainActivity的onCreate()方法中,下面这段代码的含义是:当用户选中复选框并且成功登陆一次之后,那么MyPres文件里肯定有数据了,这时如果重启登陆界面,SharedPreferences就会获取文件中数据并且呈现在输入框里了;当没有数据说明第一次打开界面或者用户不需要记住密码功能就什么也不需要显示了。

运行程序,测试一下:

并且记住密码功能也能很好的实现,这里就不展示了。如果用户选中复选框那么MyPres文件里就有数据了,见下图:

3.SQLite数据库存储

SQLite是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,在存储大量复杂的关系型数据的时可以使用,比前面学过的只适用于存储简单数据的两种存储方式要好很多。接下来学习如何创建、升级数据库以及对数据进行增删改查,并穿插一个完整的例子更好的掌握这些知识点。

(1)创建数据库

先学习一个类SQLiteOpenHelper,它是SQLiteDatabase的帮助类, 用于管理数据库的创建和升级。SQLiteOpenHelper的使用步骤:

第一步:自定义帮助类并继承SQLiteOpenHelper,并重写两个方法:onCreate()onUpgrade(),分别在这两个方法中去实现创建、升级数据库的逻辑。还需要一个构造方法,这里用含有四个参数的构造方法就可以,如图:

第二步:创建数据库时,先实例化一个自定义的帮助类,并提供四个参数,含义是(上下文,数据库名,创建Cursor的工厂类,版本号)。
第三步:用帮助类对象的getReadableDatabase()getWritableDatabase()去创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库SQLiteDatabase
第四步:之后就可以利用得到的数据库进行增删改查的操作了。

下面就来做个demo吧!从自定义帮助类开始,并重写两个方法及构造函数。在这里用帮助类帮助创建一个student表,包含学生的学号、姓名、年龄和年级,对应的SQL语句就放在一个字符串常量里。特别要注意语句一定要准确,多个空格都会建表失败。在onCreate()方法里会返回一个SQLiteDatabase对象,接下来终于接触到SQLiteDatabase的第一个常用方法execSQL(),这个方法非常万能,它可接受和处理SQL语句,换句话说,后面将要学习的增删改查不仅可以用提供好的现成的辅助性方法,还可直接用原生SQL语句再调用execSQL()就够了,在后面的学习中只介绍前一种方法。这里就调用execSQL()去创建表并打印一行提示的Toast。一个自定义帮助类构建好了!

然后新建布局,并放入五个按钮,对应创建和增删改查:

在主活动里获取所有按钮实例并注册点击事件,在onCreate()实例化帮助类MyHelper,指定数据库名为student.db,版本号为1。ContentValues类先跳过。

接下来实现点击创建按钮的效果:调用getReadableDatabase()创建数据库,且MyHelper的onCreate()也会执行,那么student表也被建立了。

运行程序,点击创建有Toast提示!但这不代表student表建立成功。所以到DDMS下找文件,确实有student.db数据库,但想要查看它需要别的工具,所以换一种查看方式,用adb shell来检查,命令如下:

可以证实student表成功建立了!

(2)增加数据

现在学习之前看到的ContentValues类,常用它put()方法以键值对的形式存储基本类型数据。在增和改会用到它,可以理解为键就是表中属性名,值就是表中数据。还常用方法clear()清空所有数据。

再来学习SQLiteDatabase用于增添数据的辅助性方法insert(),三个参数含义(被操作的表名,空值字段的名称,数据即ContentValues对象),第二个参数一般传入null。学会之后给student表插入两行记录吧,因为id这个属性设置了自增长所以可以不用管它:

运行程序,数据确实插入成功!

(3)删除数据

删除数据的辅助性方法是delete(),第一个参数还是表示表名,第二第三个参数用于约束删除某一行或几行的数据。比如需要删除student表中年龄大于17的记录:

运行,发现表中第二条记录果然被删除了!

(4)更改数据

update() 方法提供四个参数,(表名,ContentValues对象,约束,约束),之前都学过了!来试试给表里唯一的学生Lucy的年级更改为高三:

更改成功!

(5)查询数据

查询方法quary()复杂一些,需要至少七个参数(table, columns, selection, selectionArgs, groupBy, having, orderBy),含义是:(表名,要查询出的列名,查询条件子句,对应于selection语句中占位符的值,要分组的列名,分组后过滤条件,排序方式)。其实也不用害怕,多数情况下少数几个参数就能完成查询操作了。

还没完,这个方法会返回一个Cursor,查询到的数据都会从它取出。Cursor常用方法:moveToFirst()将指针移动到结果集的第一行;getColumnIndex()获取某一列在表中对应位置的索引;get某某某()传入索引以获取相应位置的某种类型的数据;close()关闭指针。下面来查询student表中所有数据:

打印出的日志结果如图:

(6)升级数据库

MyHelper里需要重写的第二个方法onUpdate()用于帮助数据库进行版本更新。比如此刻需要在数据库再添加一张表course,只要在update()写好创建course的操作,然后想办法让它被调用就好了。还记得在实例化帮助类是需要传入的第四个参数版本号吗?之前的传入的是1,只要传入一个比1大的数就可以让update()执行了。在下图代码里利用了oldVersion去判断旧版本号,如果是1就只需要再建course表,如果初次运行程序,就只会执行onCreate()方法然后两张表就一起建立了。这样做的好处是无论更新到第几代都不会影响之前的操作数据,也能保证当前版本是最新的。

修改版本号为2:

重新运行程序,点击创建,student表不会再创建而只会创建course表!

补充阅读:Litepal是一个轻型的数据库操作框架,采用了对象关系映射的模式,并对常用的数据库操作进行了封装,使用它会方便很多。感兴趣可见:项目主页使用方法.

数据持久化技术就学习到这里~

> 下一篇预告:组件篇之ContentProvider

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • 持久化技术 数据持久化就是讲那些内存中的瞬时数据保存到储存设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不...
    染微言阅读 381评论 0 0
  • 1.引言   一般在做一些面试题的时候,Android有几种数据存储方案这个问题是经常碰到的。在我们实际应用中,任...
    忆念成风阅读 2,132评论 0 10
  • 潜道阅读 247评论 0 1
  • 牙齿 ,是我们每一个人都拥有的器官,它们对于我们每天的生活来说真可谓不可或缺,我们用它们来咀嚼食物,我用依靠它们来...
    TealunDu阅读 258评论 0 0
  • 故事的开头是倒述的,画面上只有安生与苏家明。只有看到了后面,才知道途中经历了什么。 七月说,她与安生之间,是...
    传奇小黑猫阅读 204评论 0 1