Для начала давайте разберемся, что такое Depot и зачем он может понадобиться в приложениях для Palm WebOS.
Если ваше приложение должно хранить данные, то в таком случае есть три варианта:
- Использование Cookies
- Использование базы данных SQLite
- Использование Depot
Но в каких же случаях есть смысл использовать каждый из перечисленных вариантов? Если необходимо сохранить небольшой объем данных, например настройки приложения, то лучше использовать Cookies. Если же объем данных относительно большой, то выбор должен быть сделан в пользу одного из оставшихся способов. Какой из них лучше?
Что лучше использовать – зависит от объема данных, которые нужно хранить, а также от того, где вы будете хранить эти данные. Если вы используете хранилище по умолчанию (кстати Depot переводится как “хранилище” или “склад”), то у вас объем данных будет ограничен одним мегабайтом.
Если вам необходимо хранить данные в структурированном виде, то лучше сделать выбор в пользу базы данных SQLite.
Кстати, ограничение на 1 МБ данных можно обойти, разместив хранилище на разделе с медиа. В этом случае размер хранилища будет ограничен только объемом свободной памяти на это мразделе.
В чем же отличие Depot от базы данных SQLite? Depot может хранить только объекты. Например сделать так чтобы хранилась только булевая переменная не получится, нужно обязательно сделать объект и эту булевую переменную указать в виде свойства.
{ "value" : true }
Тоесть, что получается: Depot – это неструктурированное хранилище объектов. На самом деле это просто еще один уровень абстракции над API по работе с базами данных SQLite, но он позволяет избавиться от необходимости писать SQL в коде, что довольно удобно.
Перед тем, как рассматривать пример использования Depot, давайте создадим каркас приложения и потом в него уже будем добавлять необходимый функционал:
app/views/main/main-scene.html
<div id="main" class="palm-hasheader"> <div class="palm-header">Depot Test</div> <div id="AddSceneButton" x-mojo-element="Button"></div> <div id="info" x-mojo-element="x-body-text"></div> </div>
app/assistants/main-assistant.js
function MainAssistant() { } MainAssistant.prototype.setup = function() { this.controller.setupWidget("AddSceneButton", {}, {label:"Add"}); Mojo.Event.listen(this.controller.get("AddSceneButton"), Mojo.Event.tap, this.handleAddSceneButton.bind(this)); } MainAssistant.prototype.handleAddSceneButton = function(event) { this.controller.stageController.pushScene("add"); }
app/views/add/add-scene.html
<div id="main" class="palm-hasheader"> <div class="palm-header left" id="list-header"> Add / replace data </div> </div> <div class="palm-group"> <div class="palm-group-title"><span x-mojo-loc="">Database Info.</span></div> <div class="palm-list"> <div class='palm-row first'> <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true"> <div class="title"> <div class="label">Key</div> <div id="keyField" name="keyField" x-mojo-element="TextField" ></div> </div> </div> </div> <div class='palm-row last'> <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true"> <div class="title"> <div class="label">Text</div> <div id="textField" name="textField" x-mojo-element="TextField" ></div> </div> </div> </div> </div> </div> </div> <div id="depotResult" class="info-text"></div> <div x-mojo-element="Button" id="add_button"></div> <div x-mojo-element="Button" id="back_button"></div>
app/assistants/add-assistant.js
function AddAssistant() { } AddAssistant.prototype.setup = function() { this.controller.setupWidget('keyField', { hintText: 'Enter key here', modelProperty: 'originalValue', textCase: Mojo.Widget.steModeLowerCase, focus: true, maxLength: 30 }, { originalValue : '' }); this.controller.setupWidget('textField', { hintText: 'and some text here', modelProperty: 'originalValue', textCase: Mojo.Widget.steModeLowerCase, multiline: false, focus: false, maxLength: 30 }, { originalValue : '' }); this.controller.setupWidget("add_button", {}, {label:"Add entry"}); this.controller.setupWidget("back_button", {}, {label:"Back to main view"}); Mojo.Event.listen(this.controller.get("add_button"), Mojo.Event.tap, this.handleAddButton.bind(this)); Mojo.Event.listen(this.controller.get("back_button"), Mojo.Event.tap, this.handleBackButton.bind(this)); } AddAssistant.prototype.cleanup = function() { this.controller.stopListening( this.controller.get('add_button'), Mojo.Event.tap, this.handleAddButton); this.controller.stopListening( this.controller.get('back_button'), Mojo.Event.tap, this.handleBackButton); } AddAssistant.prototype.deactivate = function(event) { } AddAssistant.prototype.handleAddButton = function(event) { } AddAssistant.prototype.handleBackButton = function(event) { this.controller.stageController.popScene(); }
На главной форме у нас находится кнопка Add, которая вызывает сцену, в которой можно добавить новые записи в Depot.
Форма добавления новых записей содержит заголовок, группу из двух текстовых полей и две кнопки – кнопку добавления новой записи и кнопку закрытия сцены.
Ну вот, GUI готово, теперь можем начинать работу с Depot.
function MainAssistant() { var options = { name: "depot_tutorial", //Название хранилища (обязательный параметр) version: 1, //Версия базы данных. (опционально, по умолчанию 1) replace: false // открывать существующее хранилище }; this.depot = new Mojo.Depot(options, this.dbConnectionSuccess.bind(this), this.dbConnectionFailure.bind(this)); } MainAssistant.prototype.dbConnectionSuccess = function() { this.controller.get("info").update('OK'); } MainAssistant.prototype.dbConnectionFailure = function() { this.controller.get("info").update('Error'); }
При создании объекта Depot можно указать методы, которые будут отрабатывать при успешном подключении к хранилищу или же при ошибке подключения.
Если надо создать хранилище на разделе с медиа, то название хранилища будет выглядеть так:
name: "ext:depot_tutorial"
У нас есть сцена, в которой должно происходить добавление объектов в Depot. Нам надо передать в нее объект Depot в качестве параметра. Сделать это можно вот как:
app/assistants/main-assistant.js
MainAssistant.prototype.handleAddSceneButton = function(event) { this.controller.stageController.pushScene("add", this.depot); }
app/assistants/add-assistant.js
function AddAssistant(arg) { this.depot = arg; }
Мы передаем объект Depot в качестве параметра pushScene() и этот объект будет получен сценой как параметр конструктора.
Теперь нам необходимо написать обработчик кнопки add_button, в котором значение из текстового поля TEXT будет добавляться в хранилище с ключем KEY.
AddAssistant.prototype.handleAddButton = function(event) { this.data = { "value" :this.textModel.originalValue }; this.depot.simpleAdd(this.keyModel.originalValue, this.data, this.dbAddSuccess, this.dbAddFailure); } AddAssistant.prototype.dbAddSuccess = function(event) { this.depotResult.innerHTML = ("Add success!"); } AddAssistant.prototype.dbAddFailure = function(event) { this.depotResult.innerHTML = ("Add failure!"); }
В обработчике кнопки Add мы создаем объект, в нем в свойстве value запоминаем введенный текст и затем записываем в Depot. Запись происходит путем вызова метода simpleAdd(), в котором мы указываем ключ, сохраняемый объект, а также два callback-метода, которые будут вызваны при удачном или неудачном завершении операции записи.
И вот, мы научились добавлять объекты в Depot. Теперь попробуем научиться их оттуда доставать.
Создадим новую сцену с названием get.
app/views/get/get-scene.html
<div id="main" class="palm-hasheader"> <div class="palm-header left" id="list-header"> Retrieve data </div> </div> <div class="info-text">Which data entry you want to get?</div> <div class="palm-group"> <div class="palm-group-title">Enter key string</div> <div class="palm-list"> <div class="palm-row single"> <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true"> <div class="title"> <div id="entryNum" x-mojo-element="TextField" ></div> </div> </div> </div> </div> </div> <div id="response" class="info-text"></div> <div x-mojo-element="Button" id="get_button"></div> <div x-mojo-element="Button" id="back_button"></div>
app/assistants/get-assistant.js
function GetAssistant(arg) { this.depot = arg; } GetAssistant.prototype.setup = function() { this.controller.setupWidget("get_button", {}, {label:"Get value"}); this.controller.setupWidget("back_button", {}, {label:"Back to main view"}); this.controller.setupWidget('entryNum', { hintText: 'Enter key here', modelProperty: 'originalValue', textCase: Mojo.Widget.steModeLowerCase, multiline: false, focus: true, maxLength: 30 }, this.keyModel = { originalValue : '' }); Mojo.Event.listen(this.controller.get('get_button'), Mojo.Event.tap, this.handleGetButton.bind(this)); Mojo.Event.listen(this.controller.get("back_button"), Mojo.Event.tap, this.handleBackButton.bind(this)); } GetAssistant.prototype.cleanup = function(event) { this.controller.stopListening( this.controller.get('get_button'), Mojo.Event.tap, this.handleGetButton); this.controller.stopListening( this.controller.get('back_button'), Mojo.Event.tap, this.handleBackButton); } GetAssistant.prototype.handleGetButton = function(event) { this.depot.get(this.keyModel.originalValue, this.dbGetSuccess.bind(this), this.dbGetFailure.bind(this)); } GetAssistant.prototype.dbGetSuccess = function(response) { var recordSize = Object.values(response).size(); if(recordSize == 0) { this.controller.get("response").innerHTML = "No such record in the database"; } else { this.controller.get("response").innerHTML = "Data entry is: " + response.value; } } GetAssistant.prototype.dbGetFailure = function(transaction, result) { this.controller.get("response").innerHTML = "Error: " + result.message; } GetAssistant.prototype.handleBackButton = function(event) { this.controller.stageController.popScene(); }
На созданной сцене у нас есть текстовое поле, в которое можно ввести ключ для поиска в хранилище, поле для отображения результатов поиска и две кнопки – кнопка поиска и кнопка закрытия сцены.
Для получения объекта из хранилища мы используем метод get() объекта Depot. В этом методе указывается ключ и callback-методы, которые отработают при удачном или неудачном завершении транзакции.
На этом все. В этой статье мыузнали:
- Чем отличается Depot от базы данных SQLite.
- Как создать объект Depot в хранилище по умолчанию или на разделе с медиа
- Как создать соединение с Depot
- Как записать данные в Depot
- Как получить данные из Depot
- Как обрабатывать результаты транзакций в callback-методах.