Working with the Depot

If you are only interested in a simple object store without any database queries or structure, Depot will likely meet your needs. You can store up to 1 MB of data in a depot by default. Mojo provides a few simple functions that wrap the HTML 5 APIs to create, read, update, or delete a database.

Mojo.Depot() opens the depot that matches the name argument. If there is no match, it creates a new depot with that name. There are four methods:

get()

Calls the provided onSuccess handler with the retrieved object (or null if nothing matches the key). onFailure is called if an error occurs in accessing the database.

discard()

Removes the data associated with the key from the database.

add()

Updates the value of the named object.

removeAll()

Removes all data in the database by dropping the tables.

The Depot is simple to use. As with Cookie, you call Depot’s constructor with a unique name to create a new store or open an existing one. Unlike Cookie, Depot calls are asynchronous, so you will do most of your handling in callback functions. Once opened, you can save and retrieve any JavaScript object. To simplify your data handling, the Depot function will flatten the object so that it can be stored using SQL.

You do need to keep this to simple objects, as Depot is not very efficient, and if you extend it to complex objects it can impact application performance and memory. JSON objects are recommended as the best-performing. Beyond that you’ll have to experiment to see how the Depot performs with your application. Deep hierarchy, multiple object layers, array and object datatypes, and large strings are all characteristics of complex objects that may push the limits of the Depot capabilities.

Back to the News: Adding a Depot

The Depot will be used by News to store the feedlist for offline access of the stored feeds, to retain the user’s feed choices, and to maintain the stories’ unread state. Storing this state information will let us provide a better user experience at launch time and allow us to present the stored feeds quickly, without having to wait for a full sync from the various servers.

The Depot functions will be added to the Feeds data model through two new methods:

loadFeedDb()

Loads the feed database depot or creates one using the default feed list if there isn’t an existing depot.

storeFeedDb()

Writes the contents of Feeds.list array to the database depot.

The database will be loaded once, when the application is first launched, so the stage assistant is modified:

StageAssistant.prototype.setup = function() {

    // initialize the feeds model
    this.feeds = new Feeds();
    this.feeds.loadFeedDb();

The load method simply opens the depot or creates one if it doesn’t exist:

// loadFeedDb - loads feed db depot, or creates it with default list
// if depot doesn't already exist
loadFeedDb: function()  {
  // Open the database to get the most recent feed list
  // DEBUG - replace is true to recreate db every time; false for release
    this.db = new Mojo.Depot(
        {name:"feedDB", version:1, estimatedSize: 100000, replace: false},
        this.loadFeedDbOpenOk.bind(this),
        function(result) {
            Mojo.Log.warn("Can't open feed database: ", result);
        }
    );
},

Depot’s constructor first takes an object, which must include a name. This is a required property that must be unique for this depot. The version indicates the desired database version, but any version can be returned. The estimatedSize advises the system on the potential size of the database in bytes, and the replace property indicates that if a depot exists with this name, it should be opened. Should the replace property be set to true, an existing depot will be replaced. The replace property is optional; if missing, it defaults to false.

The loadFeedDbOpenOk callback will handle both the case where the feedlist had been previously saved and the case when a new database is created. The function literal is used if there is a database error. The cause of such a failure could be either that the database exists but failed to open, or that it didn’t exist and failed to be created.

In loadFeedDbOpenOk, attempt to retrieve the data with a call to the get() method. The first argument is a key, which must match the key used when the data was saved. The other two arguments are the success and failure callbacks.

If the request was successful, the callback function receives a single argument, an object with the returned data. In the following example, the success callback is loadFeedDbGetSuccess, which first tests the returned object, fl, for null. If fl is a valid object, it is assigned to feedlist and the update cycle is started to refresh the feeds:

// loadFeedDbOpenOk - Callback for successful db request in setup. Get stored
//   db or fallback to using default list
loadFeedDbOpenOk: function() {
    Mojo.Log.info("Database opened OK");
    this.db.simpleGet("feedList", this.loadFeedDbGetSuccess.bind(this),
      this.loadFeedDbUseDefault.bind(this));
},

// loadFeedDbGetSuccess - successful retrieval of db. Call
//  loadFeedDbUseDefault if the feedlist empty or null or initiate an update
//  to the list by calling updateFeedList.
loadFeedDbGetSuccess: function(fl) {
    if (fl === null) {
        Mojo.Log.warn("Retrieved empty or null list from DB");
        this.loadFeedDbUseDefault();

    } else {
        Mojo.Log.info("Retrieved feedlist from DB");
        this.list = fl;

        // If update, then convert from older versions

        this.updateFeedList();
    }
},

Should get() fail to retrieve any data, the sample code assumes that this is because we’re creating a new database rather than opening an existing one, so we pass loadFeedDbUseDefault as the second (failure case) callback. The default feedlist is assigned and, again, the feed update cycle is started with a call to this.updateFeedList():

// loadFeedDbUseDefault() - Callback for failed DB retrieval meaning no list
loadFeedDbUseDefault: function() {
  // Couldn't get the list of feeds. Maybe its never been set up, so
  // initialize it here to the default list and then initiate an update
  // with this feed list
    Mojo.Log.warn("Database has no feed list. Will use default.");
    this.list = this.getDefaultList();
    this.updateFeedList();
},

If the call to open the database fails, there is a database error and the failure callback is used. In this sample, a function literal is used to log the error. There should be some proper error handling added to notify the user and advise on recovery actions, but that’s not shown here.

The storeFeedDb() method is much less involved, but it is critical to keep the data updated. The webOS application model and user experience rely on saving data as it is entered or received, without explicit actions by the user. The News application has several points at which the data needs to be saved, and each time, calling this method will do it:

// storeFeedDb() - writes contents of Feeds.list array to feed database depot
storeFeedDb: function() {
    Mojo.Log.info("FeedList save started");
    this.db.add("feedList", this.list,
            function() {Mojo.Log.info("FeedList saved OK");},
            this.storeFeedDbFailure);
},

// storeFeedDbFailure(transaction, result) - handles save failure, usually an
//   out of memory error
storeFeedDbFailure: function(result) {
    Mojo.Log.warn("Database save error: ", result);
},

The add() method accepts the "feedList" string as the depot key and writes this.list as the stored object. The success callback is a function literal that logs the transaction, but the failure callback is another method. This is where you’d want to put recovery logic for memory full conditions, for example.

These calls can be implemented at these points in the FeedListAssistant:

AddDialogAssistant

A new feed has been added, so clearly an update is required to save that new feed and its contents.

showFeatureStory()

This might seem odd, but since this is a periodic updater, a flag can be set indicating that the data has changed (for example, from a feed update, or perhaps the unread status has changed); performing the update here implements a lazy update of the depot.

cleanup()

As a precaution, save the most recent version in case something has slipped through during execution.

News never deletes its Depot object, but you can use the discard() method to remove objects if needed. To be safe, you should only use this method after a successful open or create transaction, and you may want to include success and failure callbacks as a further precaution. The framework will remove an application’s Depot objects when the application is deleted from the device.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.155.91