第五课:保存和加载照片

我们现在可以拍照,可以展示了,还可以删除了。问题是当应用关闭的时候,this.photos里面的数据会跟着丢失。显然,当用户下次使用应用的时候发现他们的自拍不见了,他们肯定是不高兴的,所以这节课就是来学习如何制作一个数据存储服务来持久存储数据和加载数据到应用中。
这个流程的大部分我们都设置好,我们已经生成了一个‘Data’提供者,然后也已经在home.ts里面导入了,我们甚至还给他创建了一个save函数,这个函数是保存数据用的。所以,实际上我们要做的是这些:

  • 实现save函数以调用数据服务
  • 修改空空如也的Data,提供save和load功能
  • 在应用打开的时候加载照片数据到应用中

实现数据服务

现在要给data.ts添加代码了让他可以保存数据到存储中。这个服务的代码看起来简单得难以置信,所以我们先瞄一下然后再讨论。
> 修改 src/providers/data.ts 为如下:

  1. import { Storage } from '@ionic/storage';
  2. import { Injectable } from '@angular/core';
  3. @Injectable()
  4. export class Data {
  5. constructor(public storage: Storage){
  6. }
  7. getData(): Promise<any> {
  8. return this.storage.get('photos');
  9. }
  10. save(data): void {
  11. let newData = JSON.stringify(data);
  12. this.storage.set('photos', newData);
  13. }
  14. }

我们先看一下顶部的导入语句:

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

Storage是Ionic的统一存储服务,他在提供统一的API的同时会选择最佳的存储方式。
在设备上运行的时候,如果可以用SQLite插件的时候(我们早先安装过),那么他就会使用本机SQLite数据库来存放数据。鉴于SQLite数据库只在设备本机上才能运行,在SQLite不可用的情况下,Storage还会用IndexedDB, WEBSQL或者标准的浏览器localStorage
但是最好是用SQLite,因为基于浏览器的本地存储不是完全可靠的,存在着被操作系统擦除的风险。数据可能会随时被删掉显示是很难接受的。
我们看看getData函数:

  1. getData(): Promise<any> {
  2. return this.storage.get('photos');
  3. }

这个函数提供给我们获取存储的最新的数据。storage的get方法将返回一个promise,但是注意,我们没有在promise完成的时候做任何操作。这样我们可以在任意调用这个函数的地方处理就可以了,这样的话应用的工作流就更明了。(希望描述简单明了)
接着,我们有一个save函数,用来操作实际的数据存储:

  1. save(data): void {
  2. let newData = JSON.stringify(data);
  3. this.storage.set('photos', newData);
  4. }

我们将所有数据都存储成一个单独的JSON字符串,所以我们先调用了JSON.stringify函数然后通过storage的set方法存储。
这就是存储数据的全部,真心不复杂啊亲。现在我们来处理从存储中加载数据回应用。也就是我们接下来要处理的是loadPhotos函数。
> 修改 src/pages/home/home.ts 的 loadPhotos 函数:

  1. loadPhotos(): void {
  2. this.dataService.getData().then((photos) => {
  3. let savedPhotos: any = false;
  4. if(typeof(photos) != "undefined"){
  5. savedPhotos = JSON.parse(photos);
  6. }
  7. if(savedPhotos){
  8. savedPhotos.forEach(savedPhoto => {
  9. this.photos.push(new PhotoModel(savedPhoto.image, new
  10. Date(savedPhoto.date)));
  11. });
  12. }
  13. if(this.photos.length > 0){
  14. let today = new Date();
  15. if(this.photos[0].date.setHours(0,0,0,0) === today.setHours(0,0,0,0)){
  16. this.photoTaken = true;
  17. }
  18. }
  19. this.loaded = true;
  20. });
  21. }

我们首先调用了数据服务里的getData()函数。这个函数会以JSON字符串的方式返回所有照片数据,所以我们第一个要做到事情是对这个字符串进行JSON解码将他解析成一个可以直接使用的对象,如果没有照片数据返回的话应该是一个空数组。
如果存储中加载照片数据成功的话,我们就可以通过这些数据,给他们重建照片数据模型。接着,我们又要判断用户今天是否还能拍照。我们检查第一位的照片的日期是否就是今天,如果是的话photoTaken就设为true。
一旦这些都执行完成,我们将this.loaded设为true来标记所有照片都加载完成。现在,我们只剩下save函数调用数据服务的函数。
我们移步来完成save函数的定义。
> 修改home.ts的save函数为如下:

  1. save(): void {
  2. this.dataService.save(this.photos);
  3. }

现在,当你调用save函数的时候,他都会把当前的this.photos传入到数据服务进行存储。

总结

这节课相当的简单,所以希望你能够从上一节课程中缓过来。保存和加载数据听起来很复杂,但是,你看,保存简单的数据还是蛮简单的。
下一节课,我们将做些稍微好玩的事情,我们将要完成Slideshow页,这样我们可以看到用户的所有照片的滑动展示页,同时完成的还有我们自定义的“Days Ago”管道。