React Native开发React-Native 开发阵营React Native开发经验集

浅析 Realm 在 React-Native 中的使用

2018-12-15  本文已影响7人  8e750c8f0fae

在开发中有些数据我们需要在本地进行持久化存储,在需要的地方调用。一般来说,我们会用到 AsyncStorage 来对数据进行持久化的存储,这是官方推荐使用的存储方式,类似于 iOS 中的 NSUserDefault ,区别在于,AsyncStorage 只能存储字符串键值对,而 NSUserDefault 可以存储字符串和 number。如此,当我们需要存储的数据规模较为庞大时,需要考虑选择另一种持久化的存储方式-- Realm

Realm:与 SQList 进行数据存储相比,在性能上,各有优势,但是操作上,Realm 有明显优势,更方便使用。其中囊括了各端的使用,包括

接下来我们就来看看怎么使用 Realm

1.安装

npm install --save realm

2.链接

react-native link realm

需要注意有两点:

1.安卓端可能使用 link 无效,这时可以进行以下步骤:

include ':realm'
project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
// When using Android Gradle plugin 3.0 or higher
dependencies {
  implementation project(':realm')
}

// When using Android Gradle plugin lower than 3.0
dependencies {
  compile project(':realm')
}
import io.realm.react.RealmReactPackage; // add this 

import public class MainApplication extends Application implements ReactApplication {
    @Override
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new RealmReactPackage() // add this line
        );
    }
}

2.因为我是在0.56版本上开大,因此需要固定选择安装的版本为 2.16.0,记住把2上面的 ^ 去掉。

3.初步使用:

Realm.open({
      schema: [{name: 'Dog', properties: {name: 'string'}}]
    }).then(realm => {
      realm.write(() => {
        realm.create('Dog', {name: 'Rex'});
      });
      this.setState({ realm });
    });

4.介绍:

Realm JavaScript enables you to efficiently write your app’s model layer in a safe, persisted and fast way. It’s designed to work with React Native

意思是在 RN 上用很快,很安全,很棒棒的。

来看一个例子:

//在文件中引入 realm
const Realm = require('realm');

// 创建数据模型,并且在 properties 中创建属性
const CarSchema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: {type: 'int', default: 0},
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name:     'string',
    birthday: 'date',
    cars:     'Car[]',
    picture:  'data?' // optional property
  }
};

//realm 使用的特别之处,把创建的数据模型整合到 schema  之中,通过 open 方法打开一条 Realm
Realm.open({schema: [CarSchema, PersonSchema]})
  .then(realm => {
    // 只能在 write 方法中操作数据,查询则不用
    realm.write(() => {
    //create 创建数据的方法
      const myCar = realm.create('Car', {
        make: 'Honda',
        model: 'Civic',
        miles: 1000,
      });
      // 更新数据
      myCar.miles += 20; 
    });

    // 查询,返回数组
    const cars = realm.objects('Car').filtered('miles > 1000');
    
    //这个时候长度是1
    cars.length // => 1

    // 再次新增另一条数据
    realm.write(() => {
      const myCar = realm.create('Car', {
        make: 'Ford',
        model: 'Focus',
        miles: 2000,
      });
    });

    // 查询结果更新,变成2
    cars.length // => 2
  })
  .catch(error => {
    console.log(error);
  });

4.Realm 独有的管理工具--> Realm Studio

用于查看存储在本地的数据

MacLinuxWindows 版本

5.详解

Realm.open({schema: [Car, Person]})
  .then(realm => {
    // ...use the realm instance here
  })
  .catch(error => {
    // Handle the error here if something went wrong
  });

open 方法是打开数据库的方法,
open(config: Realm.Configuration): ProgressPromise;,

还有一个是异步线程上的使用:static openAsync(config: Realm.Configuration, callback: (error: any, realm: Realm) => void, progressCallback?: Realm.Sync.ProgressNotificationCallback): void

Configuration 里带有很多参数,我们进去看看:

interface Configuration {
        encryptionKey?: ArrayBuffer | ArrayBufferView | Int8Array;
        migration?: (oldRealm: Realm, newRealm: Realm) => void;
        shouldCompactOnLaunch?: (totalBytes: number, usedBytes: number) => boolean;
        path?: string;
        readOnly?: boolean;
        inMemory?: boolean;
        schema?: (ObjectClass | ObjectSchema)[];
        schemaVersion?: number;
        sync?: Partial<Realm.Sync.SyncConfiguration>;
        deleteRealmIfMigrationNeeded?: boolean;
        disableFormatUpgrade?: boolean;
}

着重讲几个参数:

6.数据模型

当初始化的时候,通过创建的 Realm,数据模型伴随着 schema 的生成而创建,每个 schema 包含 name(模型名称),primaryKey(唯一标志符,通常用于数组),properties(属性)

const CarSchema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: {type: 'int', default: 0},
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name:     'string',
    birthday: 'date',
    cars:     'Car[]'
    picture:  'data?', // optional property
  }
};

// Initialize a Realm with Car and Person models
Realm.open({schema: [CarSchema, PersonSchema]})
  .then(realm => {
    // ... use the realm instance to read and modify data
  })

7.参数类型

参数类型有7种,bool,int,float,double,string,data,date

注意的点

const PersonSchema = {
  name: 'Person',
  properties: {
    realName:    'string', // 必填属性
    displayName: 'string?', // 选填属性
    birthday:    {type: 'date', optional: true}, // 选填属性
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name: 'string',
    testScores: 'double?[]'
  }
};

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

realm.write(() => {
  let charlie = realm.create('Person', {
    name: 'Charlie',
    testScores: [100.0]
  });

  
  charlie.testScores.push(null);

  
  charlie.testScores.push(70.0);
  
  console.log('charlie.testScores==',charlie.testScores)//打印结果:{ '0': 100, '1': null, '2': 70 }
});

8.数据操作

try {
  realm.write(() => {
    realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'});
  });
} catch (e) {
  console.log("Error on creation");
}
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
});
realm.create('dtList'{realmId :realmId,editDataType:'DELETE'},true);

需要注意的还有一点:

根据文档上的解释:

If your model class includes a primary key, you can have Realm intelligently update or add objects based off of their primary key values. This is done by passing true as the third argument to the create method:

需要设置 primary key,这个一开始我以为是随便填,原来用处是在这里,这个 primary key 是跟 properties 内的一个参数相关联,因此需要设置一个类似 id 的主键,以此来做修改指定数据的依据。

除了用 id 做主键,如果存储的数据大,并且还涉及到与后台的信息同步,那就可以用生成随机 UDID 的方法:

export function  getUUID(){
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        }).toUpperCase();
}

这样在创建数据或者修改的时候就不会出现涉及到被覆盖的数据。

在结束操作的时候,需要执行关闭数据库操作的处理,这样避免 realm 一直占用线程资源,程序发生奔溃现象。

realm.close()

上一篇下一篇

猜你喜欢

热点阅读