最近试着做了一个GoogleGears离线应用的demo,写一点心得体会,算是一份笔记,也算是一种分享。
对Web系统来说,网络中断是很可能面临的问题,尤其是现在手机应用越来越多,无线信号的质量是很难保证的。对有些系统来说,如果不想因为网络中断而影响 工作的话,那么,开发离线操作还是很有必要的。在离线状态下,仍然可以批量录入数据,等网络连接好后,再将离线状态下录入的数据,一次性向服务器上传。
GoogleGears做Web系统的离线应用有很多的优势。首先,这是免费的,普通、智能手机以及PDA都可以自由的安装这样一个应用,不必要专门的定制终端。其次,这是一个轻量级的应用,占用很少的系统资源,并且主要的操作在客户端,不会增加服务器的负担。
现在我们来看开发这样一个应用需要做什么工作。在谷歌官网下载一个Gears的插件,地址是http://gears.google.com 按照网页的提示安装即可,做为开发者来说,有必要下载gears的tool,在tools里有两个文件:gears_init.js和 dbquery.html,gears_init.js包含着gears应用需要的javascript对象,dbquery.html则可以操作 Gears自带的轻量数据库,执行SQL命令。
由于主要的任务都在客户端完成,所以,主要的开发由javascript来完成,在需要做离线的页面上引入gears_init.js和common.js,我们要写的程序,都在common.js中:
1.由于离线开发需要客户端安装Gears插件,所以第一步需要判断客户机是否安装了该插件,如果没有,那么URL转发至Gears的安装页面(gears.google.com),如果有,那么创建google对象,代码如下:
var url = window.location.href;
if (!window.google || !google.gears) {
var message = "Sorry, you must install Google Gears first!";
var url = window.location.href+"";
location.href = "http://gears.google.com/?action=install&message="+ message +
"&return="+url;
}
2.离线录入的原理是在网络中断的情况下,暂时将数据保存在Gears提供的sqlite中,所以接下来我们需要在客户机本地的sqlite中创建表,不需要专门创建某个数据库,直接open即可。代码如下:
var db;
var success = false;
/**
* openDB
*
* 打开本地数据库
*/
function openDB() {
if (window.google && google.gears) {
try {
db = google.gears.factory.create('beta.database', '1.0');
if (db) {
// 打开BookHotel数据库
db.open('BookHotel');
db.execute('create table if not exists booking' +
' (bookingid varchar(50), '
+'hotelid varchar(50), '
+'userid varchar(50), '
+'indate varchar(50), '
+' outdate varchar(50), '
+' preference varchar(50), '
+' smoking varchar(50), '
+' creditcard varchar(50), '
+' creditcardname varchar(50), '
+' expiryMonth varchar(50), '
+' expiryYear varchar(50), '
+' Timestamp int);');
success = true;
dbcnt();
document.getElementById('offline').innerHTML = "Count: " + Offcnt;
}
} catch (ex) {
//addStatus('Could not create database: ' + ex.message);
}
}
}
3.第三个重要的地方是,在点击按钮提交时,需要首先判断网络状态,如果online,则正常提交业务,如果offline,则开始离线的业务流程。
/**
* doHttpRequest
*/
function doHttpRequest() {
createXMLHttpRequest();
//组合欲向服务器传递的参数串
//var query = createQuery();
var url = 'home1.jsp';
request.open('GET',url, true);
request.onreadystatechange = callback;
request.send(null);
}
/**
* callback
*/
function callback() {
if(request.readyState == 4) {
try{
if(request.status == 200) {
//在线时提交表单
document.BookingInput.submit();
clear();
}else{
alert("Your network is ineffective now! But you can still work offline!");
LocalSubmit();
//sendRequestForCheck();
return false;
}
}catch(e){
alert("Your network is ineffective now! But you can still work offline!");
LocalSubmit();
//sendRequestForCheck();
return false;
}
}
}
/**
* LocalSubmit
* This method is used internally
*
* 从页面获取数据并插入本地数据库中
*/
function LocalSubmit() {
var hotelid = document.getElementById('BookingInput:hotelidDecorate:hotelid').value;
var userid = document.getElementById('BookingInput:useridDecorate:userid').value;
var indate = document.getElementById('BookingInput:checkinDateDecorate:checkinDateInputDate').value;
var outdate = document.getElementById('BookingInput:checkoutDateDecorate:checkoutDateInputDate').value;
var preference = document.getElementById('BookingInput:bedsDecorate:beds').value;
var smoking = document.getElementById('BookingInput:smokingDecorate:smoking').value;
var creditcard = document.getElementById('BookingInput:creditCardDecorate:creditCard').value;
var creditcardname = document.getElementById('BookingInput:creditCardNameDecorate:creditCardName').value;
var expiryYear = document.getElementById('BookingInput:creditCardExpiryDecorate:creditCardExpiryYear').value;
var expiryMonth = document.getElementById('BookingInput:creditCardExpiryDecorate:creditCardExpiryMonth').value;
var currTime = "";
var d =new Date();
currTime += d.getFullYear()+ "-";
currTime += (d.getMonth() + 1) + "-";
currTime += d.getDate();
currTime += " "+d.getHours();
currTime += ":"+d.getMinutes();
currTime += ":"+d.getSeconds();
insert(hotelid, userid, indate, outdate, preference, smoking, creditcard, creditcardname,expiryMonth, expiryYear, currTime );
Offcnt = Offcnt + 1;
document.getElementById('offline').innerHTML = "Count: " + Offcnt;
clear();
}
/**
* insert
*
*/
function insert(hotelid, userid, indate, outdate, preference, smoking, creditcard, creditcardname,expiryMonth, expiryYear, Timestamp ) {
if (!google.gears.factory || !db) {
return;
}
// Insert the new item.
// The Gears database automatically escapes/unescapes inserted values.
alert("insert into db");
var bookingid = Offcnt + 1;
db.execute('insert into booking values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [bookingid, hotelid, userid, indate, outdate, preference, smoking, creditcard, creditcardname,expiryMonth, expiryYear, Timestamp]);
}
最后,在网络连通的情况下,可以触发批量提交请求的事件,以此来调用后台相应的业务程序。
待续。。