iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 16
1

前言

一般情況下,我們建構服務時應該會想把資料儲存在後端的資料庫裡面,不管是 RDBMS 或是各種的 NoSQL,掌握資料的好處不必多說,要建立更有用的功能或是有用的分析,都來自於一點一滴累積的用戶以及用戶的資料。至於比較不重要的東西,或是 Cache 等等,則可以存在 CookieLocalStorageSessionStorage 裡面,雖然瀏覽器清掉就會不見,但也不是太大的問題。

那在手機上呢?File、SQLite 還是其它的行動裝置上的 Storage 或許都能達到功用,但避免開發上的麻煩並跨平台應該還是我們首要的目標之一。

AsyncStorage

AsyncStorage 是唯一官方支援的儲存方式,提供非同步 Key-Value 的存取方式,在 iOS 會把小的值儲存在 Dictionary、大的值儲存在分開的檔案中,在 Android 上則會看裝置的支援狀況選用 RocksDB 或 SQLite。

設值

對鍵設值會使用 AsyncStorage.setItem

static setItem(key, value, callback?) 

通常我們應該會只傳前兩個參數,然後拿回一個 Promise。例如:

try {
  await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.');
} catch (error) {
  // 儲存錯誤
}

在使用時 key 通常會依慣例命名成 @AppName:keyName

取值

取出鍵值會使用 AsyncStorage.getItem

static getItem(key, callback?)

通常我們不傳 Callback 來拿回 Promise:

try {
  const value = await AsyncStorage.getItem('@MySuperStore:key');
  if (value !== null){
    // 有值!
    console.log(value);
  }
} catch (error) {
  // 取值錯誤
}

要注意如果沒有值會拿回 null

移除值

移除鍵值會使用 AsyncStorage.removeItem

static removeItem(key, callback?) 

一樣的不傳 Callback 來拿回 Promise:

try {
  const value = await AsyncStorage.removeItem('@MySuperStore:key');
} catch (error) {
  // 刪除錯誤
}

更詳細的內容可以參閱官方文件

Realm

除了內建的 AsyncStorage 之外,另一個值得一看的跨平台選擇是 Realm。Realm 是完整的行動應用程式資料庫,可以在手機、平板、穿戴式裝置中執行,在 2014 年發佈了 Java、Objective-C 以及 Swift 的版本,在現今已有數以億計的裝置在使用它,而被許多相當知名的公司採用。

而他們在 2016 年二月的 React Conference 上發佈了 Realm React Native

定義 Model 以及 Schema

藉由 Data Model 跟 Schema 可以在 OOP (Object-Oriented Programming) 的基礎上寫出比 Key-Value 更好管理、更可讀的程式碼,這類似於我們在後端常用的 ORM (Object Relational Mapping):

class Car {}
Car.schema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: 'int',
  }
};
class Person {}
Person.schema = {
  name: 'Person',
  properties: {
    name:    { type: 'string'},
    cars:    { type: 'list', objectType: 'Car' },
    picture: { type: 'data', optional: true }, // optional property
  }
};

// 取得 Realm 支援這些 Schema 的 物件
let realm = new Realm({ schema: [Car, Person] });

自動更新結果物件

已經查詢過的結果會根據改變自己 Reactive 的更新:

let hondas = realm.objects('Car').filtered('make = "Honda"');
// hondas.length == 0

realm.write(() => {
  realm.create('Car', {make: 'Honda', model: 'RSX'});
});
// hondas.length == 1

也可以直接地去監聽改變:

realm.objects('Dog').filtered('age < 2').addListener((puppies, changes) => {
  // Do something...
});

高效能

雖然 Realm 提供了很高的易用性,而且還有以物件為主的 API,但並不因此損害效能,甚至在一般情況下效能都遠勝 SQLite 和 AsyncStorage。

詳細的內容也可以參閱 Realm 的 React Native 文件

結語

本文所提到的都是筆者覺得可用性、穩定性較為高的方案,小的一些資料直接使用內建的 AsyncStorage 來存是最簡單的,比較多而且有結構的資料使用 Realm 來存也很不錯。長遠下來說不定還會有其他的東西進到 React Native 的核心,不過目前這樣也沒什麼太大的問題。


上一篇
Day 15:Networking 直接就上手
下一篇
Day 17:活用第三方的 React Native Module
系列文
使用 Modern Web 技術來打造 Native App30

尚未有邦友留言

立即登入留言