CIS 136 Building Mobile Apps Storage CIS 136 Building Mobile Apps
Storage Options
Storage Options Many storage API’s Local Storage Web storage, simple storage, session storage Based on key/value pairs WebSQL (android, blackberry, iOS) full-featured database tables accessed via SQL queries IndexedDB (windows, blackberry) more features than LocalStorage but fewer than WebSQL Plug-in Based File API - allows you to cache data on the local file system Downloader - Downloads files to persistent Storage SQLLite - more storage and more flexibility than the standard Web SQL database
Local Storage
Local Storage App needs to store data that the user can retrieve later Might store the data somewhere that can be accessed through some server Facebook, Twitter etc. requires an Internet connection
Local Storage Reasons we might want to store some data locally: The application is completely self contained and there is no interaction with other users, so all data can be stored locally Need to store data locally for some specific functionality like a “Remember Me” feature Skip unnecessary calls to a server by storing preference settings locally Skip unnecessary calls to a server by caching other data locally Sync online and offline data so that the user can continue using the application even when they are offline Evernote /Facebook
Local Storage most basic storage option available allows you to store up to 5MB of data Unreliable Data can get wiped out use it where data loss is not an issue never use it to store sensitive data since it can be easily accessed
Local Storage a simple key-value system, using setters and getters localStorage.setItem('key', ‘value'); var someSetting = localStorage.getItem(‘key'); can only store strings to store an object or array, first convert it to a JSON string to retrieve it later, decode JSON string back into an array or object
Local Storage Permanent – localStorage() method Data is saved even when app is closed Temporary – sessionStorage() method Data is not saved when app is closed
Methods Works off of key/value pairs Note: can serialize data using json.Stringify method Set an item - Assigns a keyed item's value window.localStorage.setItem("key", "value"); Get a key - Returns the name of the key at the specified position var keyName = window.localStorage.key(0); Get an item - Returns the item identified by the specified key var value = window.localStorage.getItem("key"); Remove an item - Removes the item identified by the specified key Window.localStorage.removeItem("key"); Clear - Removes all of the key/value pairs Window.localStorage.clear();
<script> // Wait for device API libraries to load document.addEventListener("deviceready", onDeviceReady, false); // device APIs are available function onDeviceReady() { window.localStorage.setItem(“hobby", “sailing"); var keyname = window.localStorage.key(0); // keyname is now = “hobby" var value = window.localStorage.getItem(“hobby"); // value is now = “sailing“ var value2 = window.localStorage.getItem(keyname); // value is now = “sailing" window.localStorage.removeItem(“hobby"); window.localStorage.setItem(“hobby2", “riding"); window.localStorage.clear(); // localStorage is now empty } </script>
IndexedDB
IndexedDB IndexedDB combines the strengths of the LocalStorage and WebSQL stores arbitrary JavaScript objects indexed with a key, like local storage can create multiple databases, with multiple stores per database asynchronous design and search indexes provide performance benefits.
IndexedDB When you make a request, you get a request object, which provides onerror and onsuccess events properties such as result, error and readyState
Creating/Opening a Database var db; var dbName = 'myDB'; var databaseVersion = 1 var openRequest = window.indexedDB.open(dbName [,databaseVersion]); openRequest.onerror = function (e) { console.log(e.target.errorCode); }; openRequest.onsuccess = function (event) { // Database is open and initialized db = openRequest.result; … NOTE: The database is created if a database with the specified name does not exist. Only a single version of a database can exist at a time. When a database is first created, its initial version is zero
Delete A Database function deleteDatabase() { var deleteDbRequest = window.indexedDB.deleteDatabase(dbName); deleteDbRequest.onsuccess = function (event) { // database deleted successfully }; deleteDbRequest.onerror = function (e) { console.log("Database error: " + e.target.errorCode); }
Working with Object Stores a collection of data records to create/modify an object store in an existing database need to version the existing database, by opening the database for versioning In addition to the database name, add the version number as a second parameter Use a higher version than the current existing database version This invokes the onupgradeneeded event handler.
Creating/Updating an object store function createObjectStore() { var openRequest = window.indexedDB.open(dbName, 2); openRequest.onerror = function(e) { console.log("Database error: " + e.target.errorCode); }; openRequest.onsuccess = function(event) { db = openRequest.result; openRequest.onupgradeneeded = function (evt) { var employeeStore = evt.currentTarget.result.createObjectStore ("employees", {keyPath: "id"}); }
Indexes Can retrieve records in an object store using its key or indexed fields can have one or more indexes To create an index, you must version the Indexes can either be unique or non-unique function createIndex() { var openRequest = window.indexedDB.open(dbName, 2); openRequest.onsuccess = function(event) { db = openRequest.result; }; openRequest.onupgradeneeded = function (evt) { var employeeStore = evt.currentTarget.result.objectStore("employees"); employeeStore.createIndex("stateIndex", "state", { unique: false }); employeeStore.createIndex("emailIndex", "email", { unique: true }); employeeStore.createIndex("zipCodeIndex", "zip_code", { unique: false }) }
Transactions Used to perform reading and writing operations on an object store Three modes:
Retrieve a specific record using key function fetchEmployee() { try { var result = document.getElementById("result"); result.innerHTML = ""; if (db != null) { var store = window.db.transaction("employees“,”readwrite”).objectStore("employees"); store.get("E3").onsuccess = function(event) { var employee = event.target.result; if (employee == null) { result.value = "employee not found"; } else { var jsonStr = JSON.stringify(employee); result.innerHTML = jsonStr; }; catch(e){ console.log(e);
Retrieve a specific record using an index function fetchEmployeeByEmail() { try { var result = document.getElementById("result"); result.innerHTML = ""; if (db != null) { var range = IDBKeyRange.only("john.adams@somedomain.com"); var store = window.db.transaction("employees").objectStore("employees"); var index = store.index("emailIndex"); index.get(range).onsuccess = function(evt) { var employee = evt.target.result; var jsonStr = JSON.stringify(employee); result.innerHTML = jsonStr; }; } catch(e){ http://www.ibm.com/developerworks/library/wa-indexeddb/
Retrieve all records function fetchEmployeeByEmail() { try { catch(e){ var result = document.getElementById("result"); result.innerHTML = ""; var store = window.db.transaction("employees“,”readwrite”).objectStore("employees"); var request = store.openCursor(); request.onsuccess = function(evt) { var cursor = evt.target.result; if (cursor) { var employee = cursor.value; var jsonStr = JSON.stringify(employee); result.innerHTML = result.innerHTML + “ " + jsonStr; cursor.continue(); } }; catch(e){ http://www.ibm.com/developerworks/library/wa-indexeddb/