データストレージ

Cordovaアプリケーションでは、いくつかのストレージAPIを利用できます。より完全な概要と例については、html5rocksのストレージ概要チュートリアルを参照してください。

各APIには、長所と短所があり、ここにまとめられています。ニーズに最も適したものを選ぶべきです。また、異なる目的のために単一のアプリケーション内でいくつかの異なるアプローチを使用することもできます。

LocalStorage

ローカルストレージは、シンプルな同期キー/値ペアストレージを提供し、すべてのCordovaプラットフォーム上の基盤となるWebView実装でサポートされています。

使用法の概要

ローカルストレージは、window.localStorageを介してアクセスできます。次のコードスニペットは、返されたStorageオブジェクトによって公開される最も重要なメソッドを示しています。

var storage = window.localStorage;
var value = storage.getItem(key); // Pass a key name to get its value.
storage.setItem(key, value) // Pass a key name and its value to add or update that key.
storage.removeItem(key) // Pass a key name to remove that key from storage.

詳細については、以下を参照してください。

長所

  • すべてのCordovaプラットフォームでサポートされています。
  • そのシンプルで同期的なAPIは、使いやすいことを意味します。

短所

  • 文字列のみを保存するため、複雑なデータ構造はシリアライズする必要があり、シリアライズ可能なデータのみを保存できます。
  • 大量のデータではパフォーマンスが低下します。特に
    • インデックスがないため、検索にはすべてのデータを手動で反復処理する必要があります。
    • シリアライズ/デシリアライズする必要があるため、大規模または複雑な項目の保存に時間がかかります。
    • 同期APIは、呼び出しがユーザーインターフェイスをロックアップすることを意味します。
  • ストレージの合計量が限られています(通常は約5MB)。
  • iOSは、localStorageデータを、スペースが必要な場合にOSによってクリーンアップされる可能性のある場所に保存します。

IndexedDB

IndexedDB APIの目標は、LocalStorageとWebSQL APIの長所を組み合わせ、短所を回避することです。IndexedDBを使用すると、キーでインデックス付けされた任意のJavaScriptオブジェクト(構造化クローンアルゴリズムでサポートされている場合)を保存できます。事前に構造を制約したり定義したりすることなく、SQLテーブルの利点のいくつかを提供します。

IndexedDBは、LocalStorageと同様に、シンプルで理解しやすいデータモデルを提供します。ただし、LocalStorageとは異なり、データベースごとに複数のストアを持つ複数のデータベースを作成でき、その非同期APIと検索インデックスはパフォーマンス上の利点を提供します。

IndexedDBは、すべてのプラットフォームの基盤となるWebViewでサポートされており、browserプラットフォームには既知の制限があります。

Webブラウザの制限

実際の動作は、使用されているブラウザによって異なる場合があります。たとえば、SafariブラウザとFirefoxブラウザでは動作が異なる可能性があります。

使用法の概要

  • IndexedDBは非同期的に動作します。特定のデータベース操作をリクエストすると、DOMイベントを介して結果が通知されます。
  • リクエストを行うと、onerrorイベントとonsuccessイベント、およびresulterrorreadyStateなどのプロパティを提供するリクエストオブジェクトを取得します。

次のコードスニペットは、IndexedDBの簡単な使用法を示しています。

var db;
var databaseName = 'myDB';
var databaseVersion = 1;
var openRequest = window.indexedDB.open(databaseName, databaseVersion);
openRequest.onerror = function (event) {
    console.log(openRequest.errorCode);
};
openRequest.onsuccess = function (event) {
    // Database is open and initialized - we're good to proceed.
    db = openRequest.result;
    displayData();
};
openRequest.onupgradeneeded = function (event) {
    // This is either a newly created database, or a new version number
    // has been submitted to the open() call.
    var db = event.target.result;
    db.onerror = function () {
        console.log(db.errorCode);
    };

    // Create an object store and indexes. A key is a data value used to organize
    // and retrieve values in the object store. The keyPath option identifies where
    // the key is stored. If a key path is specified, the store can only contain
    // JavaScript objects, and each object stored must have a property with the
    // same name as the key path (unless the autoIncrement option is true).
    var store = db.createObjectStore('customers', { keyPath: 'customerId' });

    // Define the indexes we want to use. Objects we add to the store don't need
    // to contain these properties, but they will only appear in the specified
    // index of they do.
    //
    // syntax: store.createIndex(indexName, keyPath[, parameters]);
    //
    // All these values could have duplicates, so set unique to false
    store.createIndex('firstName', 'firstName', { unique: false });
    store.createIndex('lastName', 'lastName', { unique: false });
    store.createIndex('street', 'street', { unique: false });
    store.createIndex('city', 'city', { unique: false });
    store.createIndex('zipCode', 'zipCode', { unique: false });
    store.createIndex('country', 'country', { unique: false });

    // Once the store is created, populate it
    store.transaction.oncomplete = function (event) {
        // The transaction method takes an array of the names of object stores
        // and indexes that will be in the scope of the transaction (or a single
        // string to access a single object store). The transaction will be
        // read-only unless the optional 'readwrite' parameter is specified.
        // It returns a transaction object, which provides an objectStore method
        // to access one of the object stores that are in the scope of this
        //transaction.
        var customerStore = db.transaction('customers', 'readwrite').objectStore('customers');
        customers.forEach(function (customer) {
            customerStore.add(customer);
        });
    };
};

function displayData() {
}

詳細については、以下を参照してください。

長所

  • 優れたパフォーマンス - 非同期APIはUIをブロックせず、インデックス作成は優れた検索パフォーマンスを提供します。
  • SQLよりも理解しやすいシンプルなデータモデル。
  • WebSQLよりも柔軟な構造。
  • 複数のデータベースとオブジェクトストアは、LocalStorageよりも多くの構造を提供します。
  • トランザクションデータベースモデルの使用による堅牢性。
  • バージョニングのサポート。

短所

プラグインベースのオプション

FileSystem API

FileSystem APIは、Chromeによって実装されたW3C仕様でしたが、他のブラウザでは実装されていませんでした。ローカルファイルシステムにデータを保存および取得するためのAPIを提供し、優れたhtml5rocksの記事で詳しく説明されています。APIはどのCordovaプラットフォームでもネイティブにサポートされていませんが、Fileプラグインは、すべてのCordovaプラットフォームで利用可能な広範な実装を提供します。

SQLiteプラグイン

SQLiteプラグインは、上記で説明したWebSQLとほぼ同じAPIを提供します。主な違いは

  • Windowsプラットフォームのサポートで利用できます。
  • 事実上、サイズ制限がありません。

次のバリエーションで利用できます

  • cordova-sqlite-storage - 独自のsqlite3実装を含むコアバージョン。iOS、Android、Windowsプラットフォームをサポートしています。
  • cordova-sqlite-ext - AndroidおよびiOSでのREGEXPサポートを含む追加機能を備えた拡張バージョン。
  • cordova-sqlite-evfree - cordova-sqlite-extに似ていますが、メモリ処理が改善されています。GPL v3または商用ライセンスで利用できます。

その他のプラグイン

代替のストレージオプションを提供する他のプラグインについては、Cordovaプラグインを検索してください。