前言

因为 实战项目系列 涉及到数据持久化,这边就来补充一下。

如本文有错或理解偏差欢迎联系我,会尽快改正更新!

如有什么问题,也可直接通过邮箱 277511806@qq.com 联系我。

数据持久化

数据持久化一直都是软件开发中重要的一个环节,几乎所有的应用都具备这一项功能;那什么是数据持久化呢?—— 说白了就是数据的本地化存储,将数据存储到本地,在需要的时候进行调用。

这边我们介绍两种在 React-Native 中比较常用的存储方式

AsyncStorage:这是官方使用的存储方式,类似于 iOS 中的 NSUserDefault ,区别在于,AsyncStorage 只能存储 字符串键值对,而 NSUserDefault 可以存储 字符串和number。

Realm:今天才发现 Realm 也已经支持 React-Native ,这是新兴的移动端数据存储方式,在没有它之前,一直都是使用 sqlist 进行数据存储,在性能上,各有优势,但是操作上,Realm 有着明显优势,更方便使用。

接下来我们就来看看怎么使用它们。

AsyncStorage 简单使用

AsyncStorage方法官方文档写得很详细,这边就不对赘述了!

AsyncStorage 使用方法很简单,我们就直接上代码:

// 增加

createData() {

AsyncStorage.setItem('name', JSON.stringify('吉泽明步'), (error, result) => {

if (!error) {

this.setState({

data:'保存成功!'

})

}

});

}

// 查询

inquireData() {

AsyncStorage.getItem('name')

.then((value) => {

let jsonValue = JSON.parse((value));

this.setState({

data:jsonValue

})

})

}

// 更新

upData() {

AsyncStorage.setItem('name', JSON.stringify('苍井空'), (error, result) => {

if (!error) {

this.setState({

data:'更新成功!'

})

}

});

}

// 删除

removeData() {

AsyncStorage.removeItem('name');

this.setState({

data:'删除完成!'

})

}

AsyncStorage效果演示.gif

按照官方推荐,我们使用 AsyncStorage 前,最好进行一层封装,React-Native中文网 给我们提供了一个比较好的框架 —— react-native-storage,我们可以直接使用它,方法很简单,说明文档中说得很详细。

既然是第三方框架,那么第一部肯定就是导入到我们的工程中:

npm install react-native-storage --save

接着,我们根据创建一个 Storage 文件专门对框架进行初始化操作:

import {

AsyncStorage,

} from 'react-native';

// 第三方框架

import Storage from 'react-native-storage';

var storage = new Storage({

// 最大容量,默认值1000条数据循环存储

size: 1000,

// 存储引擎:对于RN使用AsyncStorage,对于web使用window.localStorage

// 如果不指定则数据只会保存在内存中,重启后即丢失

storageBackend: AsyncStorage,

// 数据过期时间,默认一整天(1000 * 3600 * 24 毫秒),设为null则永不过期

defaultExpires: 1000 * 3600 * 24,

// 读写时在内存中缓存数据。默认启用。

enableCache: true,

// 如果storage中没有相应数据,或数据已过期,

// 则会调用相应的sync方法,无缝返回最新数据。

// sync方法的具体说明会在后文提到

// 你可以在构造函数这里就写好sync的方法

// 或是写到另一个文件里,这里require引入

// 或是在任何时候,直接对storage.sync进行赋值修改

sync: require('./sync')

})

// 全局变量

global.storage = storage;

到这里,我们需要注意的就是要在哪里初始化这个文件,其实一个思路就是 —— 在哪个地方,我们只需要引用一次文件,就可以在其他文件中使用(比如:我们程序默认的进口就是 index.ios/android.js 文件,那么只要在他们中引用一次文件即可,这样就不需要去注意什么调用顺序,因为 index.ios/android.js 文件肯定是最先调用的,它们才是真正的王)。

然而,为了方便我们使用同一套代码,我们会创建一个 Main 文件作为程序入口的 中转总站 来管理其他的文件,然后外界只要调用这个 Main 文件,就可以展示里面的所有东西。所以,将引用放到 Main 文件中是最好的选择。

// 在 main 文件中添加

import storage from '封装的文件位置';

到这里,我们就完成了最基础的配置,我们只需要在需要用到的地方直接使用就可以了,首先我们在新建一个文件,然后从Main文件跳转到这个文件中。

接着,我们就真正地自己来使用一下这个框架:

// 增加

createData() {

// 使用key保存数据

storage.save({

key:'storageTest', // 注意:请不要在key中使用_下划线符号!

rawData: {

name:'吉泽明步',

city:'xx省xxx市'

},

// 设为null,则不过期,这里会覆盖初始化的时效

expires: 1000 * 3600

});

}

// 查询

inquireData() {

storage.load({

key:'storageTest',

// autoSync(默认为true)意味着在没有找到数据或数据过期时自动调用相应的sync方法

autoSync: true,

// syncInBackground(默认为true)意味着如果数据过期,

// 在调用sync方法的同时先返回已经过期的数据。

// 设置为false的话,则始终强制返回sync方法提供的最新数据(当然会需要更多等待时间)。

syncInBackground: true,

// 你还可以给sync方法传递额外的参数

syncParams: {

extraFetchOptions: {

// 各种参数

},

someFlag: true,

},

}).then(ret => {

// 如果找到数据,则在then方法中返回

// 注意:这是异步返回的结果(不了解异步请自行搜索学习)

// 你只能在then这个方法内继续处理ret数据

// 而不能在then以外处理

// 也没有办法“变成”同步返回

// 你也可以使用“看似”同步的async/await语法

// 更新data值

this.setState({

data: ret.name

});

}).catch(err => {

//如果没有找到数据且没有sync方法,

//或者有其他异常,则在catch中返回

console.warn(err.message);

switch (err.name) {

case 'NotFoundError':

// 更新

this.setState({

data:'数据为空'

});

break;

case 'ExpiredError':

// TODO

break;

}

})

}

// 更新

upData() {

// 重新存储即可

storage.save({

key:'storageTest', // 注意:请不要在key中使用_下划线符号!

rawData: {

name:'苍井空',

city:'xx省xxx市'

},

// 设为null,则不过期,这里会覆盖初始化的时效

expires: 1000 * 3600

});

}

// 删除

removeData() {

// 删除单个数据

storage.remove({

key: 'storageTest'

});

// storage.remove({

// key: 'react-native-storage-test',

// name:'吉泽明步'

// });

// // !! 清空map,移除所有"key-id"数据(但会保留只有key的数据)

// storage.clearMap();

//

// // 获取某个key下的所有id

// storage.getIdsForKey('user').then(ids => {

// console.log(ids);

// });

//

// // 获取某个key下的所有数据

// storage.getAllDataForKey('user').then(users => {

// console.log(users);

// });

//

// // !! 清除某个key下的所有数据

// storage.clearMapForKey('user');

}

react-native-storage效果演示.gif

Realm 配置与常见错误处理

很惊喜,Realm 也支持了 React-Native ,这样我们可以在移动端 愉快地 进行存储操作了。

而且使用方法 Realm 官方提供的文档都一如既往地详细,所以如果感兴趣,也可以到 Realm说明文档 进行学习(不知是网络问题还是官方没有整理好,我这边中文版文档是打不开的,所以只能看英文版),这边我们直接将里面常用到的内容整理出来,简单说下怎么使用。

首先,一样还是需要打开终端将 Realm 放到我们的工程中

npm install --save realm

接着,添加 Realm 与 工程的链接

React-Native >= 0.31.0

react-native link realm

React-Native < 0.31.0

rnpm link realm

配置成功.png

出现上面的提示表示成功,然后我们需要卸载模拟器中已经安装的 APP 并重新安装(Xcode会进行一系列配置,其中会在网络下载一下必要的组件,时间视网络情况而定),来测试下安卓和iOS,2端是否能正常使用

Xcode配置.png

如果出现有 err! 等字样或者在安卓中出现错误警告,说明安卓端没有成功地进行全部配置,需要我们手动进行配置,步骤如下:

如果出现 android Missing Realm constructor - please ensure RealmReact framework is included 报错:

在 MainApplication 中添加

new RealmReactPackage()

如果还是链接不上,我们检查以下几处代码是否有自动添加

settings.gradle 中是否有下面代码,不存在手动添加

include ':realm'

project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')

如果还不行,到app => build.gradle 中是否有下面代码,不存在手动添加

dependencies {

compile project(':realm') // 是否存在,不存在手动添加(再旧版本有效,新版本不需要添加此项)

compile fileTree(dir: "libs", include: ["*.jar"])

compile "com.android.support:appcompat-v7:23.0.1"

compile "com.facebook.react:react-native:+" // From node_modules

}

接着,重新运行安卓:

react-native run-android

如果还是不行,可联系官方,或者将错误代码发送给我,也许可以帮忙解决。

Realm 常用操作

作为数据库,使用它无法就是 增删改查 这老四样,使用之前,还是老规矩,初始化表格:

name:表格名称。

primaryKey:主键,这个属性的类型可以是 'int' 和 'string',并且如果设置主键之后,在更新和设置值的时候这个值必须保持唯一性,并且无法修改。

properties:这个属性内放置我们需要的字段。

// 新建表模型

const PersonSchema = {

name: 'Person',

primaryKey:'id', // 官方没给出自增长的办法,而且一般不会用到主键,这也解决了重复访问的问题,而且实际开发中我们不需要主键的,让服务端管就是了

properties: {

id:'int',

name: 'string',

tel_number: {type: 'string', default: '156xxxxxxxx'}, // 添加默认值的写法

city: 'string' // 直接赋值的方式设置类型

}

};

初始化 Realm:

// 根据提供的表初始化 Realm,可同时往数组中放入多个表

let realm = new Realm({schema: [PersonSchema]});

增加数据:

// 增加

createData() {

realm.write(() => {

realm.create('Person', {id:0, name:'吉泽明步', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});

realm.create('Person', {id:1, name:'苍井空', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});

realm.create('Person', {id:2, name:'小泽玛利亚', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});

realm.create('Person', {id:3, name:'皮皮虾我们走', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});

realm.create('Person', {id:4, name:'波多野结衣', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});

})

}

查询数据

查询所有数据:

// 查询所有数据

let persons = realm.objects('Person');

console.log ('name:' + persons[0].name + 'city:' + persons[0].city)

根据条件查询数据

// 查询

inquireData() {

let allData;

// 获取Person对象

let Persons = realm.objects('Person');

// 遍历表中所有数据

for (let i = 0; i

let tempData = '第' + i + '个' + Persons[i].name + Persons[i].tel_number + Persons[i].city + '\n';

allData += tempData

}

this.setState({

data:allData

})

}

// 根据条件查询

filteredData() {

let allData;

// 获取Person对象

let Persons = realm.objects('Person');

// 设置筛选条件

let person = Persons.filtered('id == 1');

if (person) {

// 遍历表中所有数据

for (let i = 0; i

let tempData = '第' + (person[i].id + 1) + '个数据:' + person[i].name + person[i].tel_number + person[i].city + '\n';

allData += tempData

}

}

this.setState({

data:'筛选到的数据:' + allData

})

}

更新数据:

// 更新

upData() {

realm.write(() => {

// 方式一

realm.create('Person', {id: 0, name: '皮皮虾,我们走', tel_number: '156xxxxxxxx', city: 'xx省xx市xxxxxx'}, true);

// // 方式二:如果表中没有主键,那么可以通过直接赋值更新对象

// // 获取Person对象

// let Persons = realm.objects('Person');

// // 设置筛选条件

// let person = Persons.filtered('name == 苍井空');

// // 更新数据

// person.name = '黄鳝门'

})

}

删除数据:

// 删除

removeData() {

realm.write(() => {

// 获取Person对象

let Persons = realm.objects('Person');

// 删除

realm.delete(Persons);

})

}

realm效果演示.gif

native数据类型 react_React-Native 之 数据持久化相关推荐

  1. 【redismemcached】数据类型、内存管理、数据持久化和集群管理的区别

    这几年redis很火,redis也常常被当做memcached的挑战者被提到桌面上来.关于redis和memcached的比较比比皆是.然而,redis真的在功能.性能以及内存使用效率上都超越memc ...

  2. Redis和Memcached的区别(数据类型、内存管理、数据持久化、集群管理)

    Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较: Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支 ...

  3. WebRTC Native M96 回调音频裸数据IAudioFrameObserver--采集和播放语音混音后的数据(onMixedAudioFrame)

    此前已经说道,通过注册回调,给上层APP抛音频裸数据: <WebRTC Native M96 SDK接口封装–注册语音观测器对象获取原始音频数据registerAudioFrameObserve ...

  4. 一文带你详解Redis常用的数据类型以及面试常碰到的数据持久化机制原理

    前言 关于Redis的知识点总结了一个思维导图分享给大家: 简介 Redis是一种面向"key-value"类型数据的分布式NoSQL数据库系统,支持五种数据类型格式:** Str ...

  5. iOS 数据持久化 -- Core Data (2)

    2019独角兽企业重金招聘Python工程师标准>>> 1.Core Data 是数据持久化存储的最佳方式 2.数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里, ...

  6. 【iOS数据持久化】偏好设置(UserDefaults)

    官网文档:NSUserDufaultClass Reference 关于偏好设置:AboutPreferences and Settings UserDefualts是一种便利的,通过key-valu ...

  7. 【iOS数据持久化】Plist使用

    iOS数据持久化Plist使用 iOS 端数据持久化就是把数据保存在本地,常用于基本信息储存,应用配置,应用支持数据源,网络请求缓存等.主要有如下几种方式: 方式 介绍 特点 Plist文件 属性列表 ...

  8. 数据持久化 技术比较

      [数据存储]coredata.sqlite.fmdb和sqlitepersistentobject 管理提醒: 本帖被 angellixf 从 OS X开发讨论区 移动到本区(2014-02-12 ...

  9. iOS应用数据持久化(一)

    一.iOS应用常用的数据持久化方式: 1.XML属性列表(plist) 2.preference(偏好设置) 3.NSKeyedArchiver(归档与反归档) 4.SQLite3(数据库) 5.Co ...

  10. 四种数据持久化方式(上) :属性列表与归档解档

    iOS中的永久存储,也就是在关机重新启动设备,或者关闭应用时,不会丢失数据.在实际开发应用时,往往需要持久存储数据的,这样用户才能在对应用进行操作后,再次启动能看到自己更改的结果与痕迹. iOS开发中 ...

最新文章

  1. golang beego orm mysql sqlite3 postgresql 模型字段 数据库类型 对应关系
  2. 接口隔离原则_设计模式六大原则
  3. python-面向对象
  4. arcgis python脚本实现从界面选择输入输出_ArcGIS Python脚本实现数据驱动页面的批量出图...
  5. java 内存溢出 内存泄露_JVM——内存泄漏与内存溢出
  6. HDU 3605Escape(缩点+网络流之最大流)
  7. 谈谈Dictionarylt;T1,T2gt;和Listlt;Tgt;的问题 [转]
  8. 授予数据库账号dba权限_深入理解 MySQL 用户和权限
  9. memcached linux 配置文件,Linux下Memcached服务器部署 | 系统运维
  10. java的properties文件中的换行书写
  11. WebView 的新增安全功能
  12. property自己实现
  13. PyQt5-QLineEdit控件使用
  14. [python小工具]小说分割器
  15. 把手机上B站App缓存的视频转换为正常的mp4格式视频
  16. VScode C/C++ 环境配置教程 (GCC)
  17. 所谓“螺旋方阵”,是指对任意给定的N,将1到N×N的数字从左上角第1个格子开始,按顺时针螺旋方向顺序填入N×N的方阵里。本题要求构造这样的螺旋方阵。
  18. 用CSS3制作一个风车
  19. python定义一个匿名函数使用什么关键字_python3----函数、匿名函数
  20. 【WebServerProgramming】Ch.1 网络因特网Web

热门文章

  1. WIN10下的ios开发
  2. 用JavaScript写的U校园自动答题浏览器分析
  3. sap新手学习第一天
  4. 2022下半年数学建模竞赛汇总(比赛时间、出成绩时间、难易程度、含金量、竞赛官网)
  5. 【GAN论文解读系列】NeurIPS 2016 InfoGAN 使用InfoGAN解耦出可解释的特征
  6. Opencv之.convertTo
  7. RK3399基于ubuntu文件系统的audio调试
  8. 如何解决下载慢的大问题,如neo4j等
  9. PS如何修改扩展插件的名字(Photoshop重命名插件教程)
  10. 一阶滞后环节matlab,一个一阶惯性带有滞后环节的PID仿真程序