博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
react-native Realm的使用
阅读量:5844 次
发布时间:2019-06-18

本文共 8722 字,大约阅读时间需要 29 分钟。

1.安装

//下载yarn add realm --save ornpm i realm --save以上两者二选一//进行链接库Libraryreact-native link realm复制代码

在ios使用中可能会产生一个错误

解决方法

是rnpm的问题需要在packaje.json中加入"rnpm": {    "ios": {    "project": "ios/
.xcodeproj" }}复制代码

参考博客地址:

https://www.jianshu.com/p/a1846aa8d40a

https://stackoverflow.com/questions/44725619/fatal-attempting-to-release-access-but-the-mutator-does-not-have-access

2.使用

Realm supports the following basic types: bool, int, float, double, string, data, and date.

支持数据类型:

  • bool
  • int
  • float
  • double ‘int’ and ‘double’ are stored as 64 bits while float is stored with 32 bits.
  • string
  • data data properties map to ArrayBuffer,for example:[[object object],object object],object object]]
  • date

定义一个数据模型

const CarSchema = {  name: 'Car',  properties: {    // The following property types are equivalent    make:   {
type: 'string'}, model: 'string', }}复制代码

可选属性

通常,基本数据类型是非可选(non-optional)并且不支持存储 null undefined 类型。属性可以被指定为可选类型通过指定 optional在属性定义时,或者通过简写语法(拼接?).

const PersonSchema = {  name: 'Person',  properties: {    realName:    'string', // required property    displayName: 'string?', // optional property    birthday:    {
type: 'date', optional: true}, // optional property }};let realm = new Realm({schema: [PersonSchema, CarSchema]});realm.write(() => { // optional properties can be set to null or undefined at creation let charlie = realm.create('Person', { realName: 'Charlie', displayName: null, // could also be omitted entirely birthday: new Date(1995, 11, 25), }); // optional properties can be set to `null`, `undefined`, // or to a new non-null value //可选属性可以设置为 null undefined charlie.birthday = undefined; charlie.displayName = 'Charles'; // Setting a non-optional property to null will throw `TypeError` // 非可选属性可以设置为 null // charlie.realName = null;});复制代码

增 和 改

增realm.write(() => {  // Create a book object  realm.create('Book', {id: 1, title: 'Recipes', price: 35});  // Update book with new price keyed off the id  realm.create('Book', {id: 1, price: 55}, true);});复制代码
改const carSchemea = {    name:'car',    properties:{        miles:'int'    }} let realm = new Realm.open({schema: [carSchemea})realm.write(() => {  car.miles = 1100;});复制代码

realm.write(() => {  // Create a book object  let book = realm.create('Book', {id: 1, title: 'Recipes', price: 35});  // Delete the book  realm.delete(book);  // Delete multiple books by passing in a `Results`, `List`,  // or JavaScript `Array`  let allBooks = realm.objects('Book');  realm.delete(allBooks); // Deletes all books});复制代码

Migrations(迁移)

普通迁移

当你使用数据库时,你可以多次修改你的数据模型,例如支持以下的Person模型:

const PersonSchema = {  name: 'Person',  properties: {    firstName: 'string',    lastName: 'string',    age: 'int'  }}复制代码

当我们更新我们的数据模型来新增一个 name 属性(property),如果我们简单的修改,如下:

const PersonSchema = {  name: 'Person',  properties: {    name: 'string',    age: 'int'  }}复制代码

此时,如果我们保存所有数据用之前的模型版本,这里将会产生错误,当你想要打开一个新的版本你必须要进行迁移,简而言之,如果你新增或者删除一个属性(property),你只需要将schemaVersion增加,example如下:

Realm.open({  schema: [PersonSchema],  schemaVersion: 1,  migration: (oldRealm, newRealm) => {    // only apply this change if upgrading to schemaVersion 1    if (oldRealm.schemaVersion < 1) {      const oldObjects = oldRealm.objects('Person');      const newObjects = newRealm.objects('Person');      // loop through all objects and set the name property in the new schema      for (let i = 0; i < oldObjects.length; i++) {        newObjects[i].name = oldObjects[i].firstName + ' ' + oldObjects[i].lastName;      }    }  }}).then(realm => {  const fullName = realm.objects('Person')[0].name;});复制代码

通过上面的例子我们会发现,新增字段的值可以通过原有的值做相应的转换,如果你只是单纯的新增或者删除一个字段,你只需要改变schemaVersion的值即可(原则上采用增加的方式)。

Linear Migrations

这种迁移方式解决多个版本迁移问题。

如果用户跳过应用程序更新并且在跳过的版本中多次更改了属性,就可能发生这种情况。在这种情况下,您可能需要编辑旧的迁移代码,以便将数据从旧模式正确更新到最新模式。

可以通过按顺序运行多个迁移来避免此问题,确保将数据库升级到每个以前的版本,并且运行关联的迁移代码。遵循这种模式时,永远不必修改旧的迁移代码,尽管您将需要保留所有旧的模式和迁移块以供将来使用。下面举一个例子:

const schemas = [  { schema: schema1, schemaVersion: 1, migration: migrationFunction1 },  { schema: schema2, schemaVersion: 2, migration: migrationFunction2 },  ...]// the first schema to update to is the current schema version// since the first schema in our array is atlet nextSchemaIndex = Realm.schemaVersion(Realm.defaultPath);while (nextSchemaIndex < schemas.length) {  const migratedRealm = new Realm(schemas[nextSchemaIndex++]);  migratedRealm.close();}// open the Realm with the latest schemaRealm.open(schemas[schemas.length-1]);复制代码

以上示例解决了的问题是,用户安装了应用程序记录了多个数据库版本,在以后的程序中你都可以获取到以前数据库中的数据。

Notifications 机制

Realm, Results,List 这些objects提供了 addListener方法来支持通知回调。当对象(object)更新的时候,通知回调就会被执行。

有两种通知机制的方法

  • Realm Notifications 适合简单的通知回调,当写(write transactions) 操作被提交(committed)。

  • Collection Notifications 适合更复杂的回调,当收到原数据插入(in sertions),删除(deletions)和更新(updates)

在某些情况下,写操作事物开始的时候监听者(listener)会被回调 - 数据库Realm更新到最新版本,Realm entities被观察到了修改(modified)或者删除(deleted)都会触发(triggers)通知。在这些情况中,监听者会运行在当前写事物(write transaction)的上下文环境中,一旦你想开启一个新的write transaction,将会抛出异常。你可以通过Realm.isInTransaction这个属性来判断你的code是否在执行写操作。

接下分别就两种通知机制举出example

1.Realm Notifications

Realm instances 会发出通知当写操作被提交

function updateUI() {  // ...}// Observe Realm Notificationsrealm.addListener('change', updateUI);// ..later remove the listenerrealm.removeListener('change', updateUI);// ..or unregister all listenersrealm.removeAllListeners();复制代码

2.Collection Notifications

Collection notifications are delivered asynchronously(异步分发)

class Dog {}Dog.schema = {  name: 'Dog',  properties: {    name:  'string',    age: 'int',  }};class Person {}Person.schema = {  name: 'Person',  properties: {    name:    {
type: 'string'}, dogs: {
type: 'list', objectType: 'Dog'}, }};复制代码

假设你观察a list of dog owners 通过上面的模型,你将收到通知通过通过修改来匹配Person 对象当

  • 修改Personname属性
  • 你增加或者移除 DogPersondogs属性
  • 通过修改属于Person Dogage 属性。

This makes it possible to discretely control the animations and visual updates made to the content inside your UI, instead of arbitrarily reloading everything each time a notification occurs.

原文更能表达这个含义所以不进行翻译。

// Observe Collection Notificationsrealm.objects('Dog').filtered('age < 2').addListener((puppies, changes) => {  // Update UI in response to inserted objects  changes.insertions.forEach((index) => {    let insertedDog = puppies[index];    ...  });  // Update UI in response to modified objects  changes.modifications.forEach((index) => {    let modifiedDog = puppies[index];    ...  });  // Update UI in response to deleted objects  changes.deletions.forEach((index) => {    // Deleted objects cannot be accessed directly    // Support for accessing deleted objects coming soon...    ...  });});// Unregister all listenersrealm.removeAllListeners();复制代码

3.实际运用

在实际项目开发中我们通常使用封装的思想来进行实际应用,接下来通过一个简单的案例来演示:

首先我们使用豆瓣的免费接口作为测试数据的接口

https://api.douban.com/v2/movie/in_theaters?start=0&count=20复制代码

大家可以自行通过各种方式获取请求数据,查看数据结构

1.创建数据模型对象

Schemeas.jsconst MoviesSchemea = {    name:'Movies',    properties:{        count:'int',        start:'int',        total:'int',        title:'string',        subjects: {
type:'list',objectType:'Subject'}, }}const subjectSchemea = { name:'Subject', properties:{ alt:'string', id:'string', original_title:'string', title:'string', year:'string' }};export { MoviesSchemea, subjectSchemea}复制代码

2.设置数据迁移模型

Migrations.jsimport {MoviesSchemea,subjectSchemea} from 'Schemeas'export default[{    schema:[        MoviesSchemea,        subjectSchemea,    ],    path:'movies.realm',    schemaVersion:6,    migration:(oldRealm,newRealm) => {           }}]复制代码

默认输出的是一个数组

3.设置Realm管理类

RealmManager.js//引入对应模块import Realm from 'realm'import Migrations from 'Migrations'let realm = new Realm(Migrations[Migrations.length-1])//增 改const insertMovies = (movies) => {    try {        realm.write(()=>{            let oldMovies = realm.objects('Movies');            let count = oldMovies.length;            if (oldMovies = null || count == 0){                realm.create('Movies',movies)            }else {                oldMovies[count - 1].count = movies.count;                oldMovies[count - 1].start = movies.start;                oldMovies[count - 1].total = movies.total;                oldMovies[count - 1].title = movies.title;                oldMovies[count - 1].subjects = movies.subjects;            }        })    }    catch (error){        console.log(error)    }}//查询const queryMovies = () =>{    return realm.objects('Movies')}//删除const deleteMovies = () =>{    try {        realm.write(() => {            realm.delete(realm.objects('Movies'));        })    }    catch (error){        console.log(error)    }}export {    insertMovies,    queryMovies,    deleteMovies}复制代码

这样我们一个数据库类就可以完美使用了,下面我们可以查看相应的demo来完成本次Realm的实践。

Realm 的官方文档链接:

转载地址:http://wsqcx.baihongyu.com/

你可能感兴趣的文章
Linux crontab定时执行任务
查看>>
自己遇到的,曾未知道的知识点
查看>>
docker 基础
查看>>
我的友情链接
查看>>
写Use Case的一种方式,从oracle的tutorial抄来的
查看>>
【C#】protected 变量类型
查看>>
爬虫去重(只是讲了去重的策略,没有具体讲实现过程,反正就是云里雾里)...
查看>>
react中将px转化为rem或者vw
查看>>
avcodec_open2()分析
查看>>
何如获取单选框中某一个选中的值
查看>>
QQ悬浮返回顶部
查看>>
MySQL建表语句的一些特殊字段
查看>>
腾讯前端二面题目详解
查看>>
mascara-1
查看>>
Jquery Form表单取值
查看>>
Android API level 与version对应关系
查看>>
Team Name
查看>>
String类
查看>>
西门子_TDC_数据耦合小经验
查看>>
[LeetCode] Copy List with Random Pointer
查看>>