[Ionic 2从入门到精通] 3.6 保存和加载数据

第六课:保存和加载数据

你知道什么是最烦恼的吗?如果你创建了一大个待完成的checklist,稍后回来的时候再用的时候,发现没有了。嗯,这就是应用当前的状态,所以我们将要给用户提供一个保存用户数据的途径。
我们已经为他做了一些架构准备,我们订阅了我们的Observable在每次数据变更的时候都调用了save函数,我们只需要现在来实现这个函数就可以了。
> 修改 src/pages/home/home.ts 里面的 save 方法:

save(): void {
    Keyboard.close();
    this.dataService.save(this.checklists);
}

如果你不健忘的话,早些时候我们已经生成和导入了一个数据服务,所以我们这里只需要调用他并传入checklists数据。当然,我们目前还没有实现这个数据服务,所以他现在不会对数据做任何事情,我们现在就来弥补他。注意,我们也调用了Keyboard的close方法,由于会在任何数据项变更的时候调用save方法,我们可以用他来在用户添加或者编辑完数据之后确保键盘关闭。

保存数据

我们现在要给data.ts码代码了,让他可以将传入的任何数据保存到存储里面去。实际上这个服务的代码相当的简单,我们来看看:
> 修改 src/providers/data.ts :

import { Storage } from '@ionic/storage';
import { Injectable } from '@angular/core';

@Injectable()
export class Data {
    constructor(public storage: Storage){
    }

    getData(): Promise<any> {
        return this.storage.get('checklists');
    }
    save(data): void {
        let saveData = [];
        //Remove observables
        data.forEach((checklist) => {
            saveData.push({
                title: checklist.title,
                items: checklist.items
            });
        });

        let newData = JSON.stringify(saveData);
        this.storage.set('checklists', newData);
    }
}

这里有个我们之前没见过的导入:

import { Storage } from '@ionic/storage';

Storage是Ionic的统一存储服务,他负责使用最好的方式来存储数据的同时提供了一个统一的API给供我们使用。
当在设备上运行的时候,如果SQLite插件是可用状态的话(我们之前安装过了),他将会使用本地(native)SQLite数据库来存储数据。由于SQLite数据库只在设备上可用,在SQLite不可用的情况下,Storage也会用IndexedDB,WebSQL或者标准浏览器的localStorage。
尽可能使用SQLite,因为基于浏览器的本地存储不大可靠可以被操作系统默默的清理掉。如果你的数据可以被随机清理掉的话显然很不理想。
我们来看看getData函数:

getData(): Promise<any> {
    return this.storage.get('checklists');
}

这个函数允许我们获取最新的存储数据,他会以Promise的方式返回数据。我们将此函数的返回的Promise的返回类型设置为<any>类型,这是一个更复杂的类型。记住,这不是唯一可用类型,所以,如果你觉得很迷惑的话,你可以什么都不加,像这样:

getData(){
    return this.storage.get('checklists');
}

注意,在这里我们没有给promise完成的时候添加处理器,我们只是返回get方法的结果(一个解析当前存储数据的promise)。记住,这个行为不是瞬间完成的,这样我们可以在调用这个函数的任何地方添加处理器,也更像应用的工作流。(希望这个能够更简单明了)
然后,我们来到了saveData函数,这个函数用于将数据保存到存储里:

save(data): void {
    let saveData = [];

    //Remove observables
    data.forEach((checklist) => {
        saveData.push({
            title: checklist.title,
            items: checklist.items
        });
    });

    let newData = JSON.stringify(saveData);
    this.storage.set('checklists', newData);
}

之前提到我们,我们将数据存为一个简单的JSON编码字符串,所以我们调用了JSON.stringify函数然后使用set方法将他保存到存储对象里去。在做这些之前,我们把数据的observable移除掉只加入title和items,因为他们跟JSON不搭调(他会引起circular对象错误),我们后面会重新创建它们。
这就是保存数据的全部内容,也没那么复杂。我们接下来处理加载数据到应用中。

加载数据

任何时候当用户打开应用,我们都需要从存储中加载checklists数据,所以最适合做这个操作的地方是home页的ionViewDidLoad,这个函数会在页面加载完成的时候触发。我们将对构造器进行小小的变更。
> 在 src/pages/home/home.ts 中修改constructor和ionViewDidLoad:

constructor(public nav: NavController, public dataService: Data, public
alertCtrl: AlertController, public platform: Platform) {
}
ionViewDidLoad(){
this.platform.ready().then(() => {
    this.dataService.getData().then((checklists) => {

        let savedChecklists: any = false;

        if(typeof(checklists) != "undefined"){
            savedChecklists = JSON.parse(checklists);
        }
        if(savedChecklists){
            savedChecklists.forEach((savedChecklist) => {
                let loadChecklist = new ChecklistModel(savedChecklist.title, savedChecklist.items);
                this.checklists.push(loadChecklist);
                loadChecklist.checklist.subscribe(update => {
                    this.save();
                });
            });
        }
    });
});
}

我们调用了数据服务里面刚定义的getData函数。之前也提过,getData函数返回一个promise而不是直接返回数据,这样我们可以在加载完成之后处理响应。如果getData直接返回数据的话,当我们想要访问他的时候可能他都没有返回。
所以我们一直等待取回数据,然后将checklists传入到我们的处理器。首先我们解码JSON字符串到数组到这样我们就可以用来,然后我们循环数组里的每个数据项,基于这些数据创建一个新的Checklist Data。循环数据和创建新的模型而不是直接将this.checklists设置为savedChecklists的原因是在保存checklists将他转换成JSON字符串的时候他就丧失了使用数据模型里的助理函数的能力。所以,我们得利用取得的标题和数据项来为所有的checklists创建新的对象。
最后,我们重新给Observable设置监听器,这样当数据改变的时候就会被处罚。重点关注我们所作的这些都是在platform.ready()调用里面进行的,如果在设备准备好之前这么做的话将会发生问题。

总结

这就是本节课的所有内容,数据现在在进行任何变更后可以被保存到SQLite数据里面去,应用重新打开的时候,所有数据将会重新加载回来。试一下添加一些checklist或者修改checklist的状态,然后重新加载应用看看对他进行的变更是否还在。

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

推荐阅读更多精彩内容