最近做一个webapp,需要将webview的数据存储到本地数据库,鉴于Android和webview传递大量数据比较麻烦,所以干脆直接存储在webview内置的本地数据库算了。 LocalStore 没有时间限制的本地存储,是上面三种存储方式中浏览器默认存储的容量最小的,也是最容易使用的,直接一句话完成存储过程。 存储数据:
localStorage.XXX=YYYXXX可以随便命名,YYY是要存储的数据,可以是任何数据类型。 例如:
localStorage.status=truelocalstore适合做少量数据的存储,一般用来存储网站某个变量的状态之类的
清除数据,有两种方式: 1) 删除一条数据
localStorage.removeItem(“key”);Key对应上面的XXX 2)批量删除数据
localStorage.clear();在浏览器可以看到其存储的数据,例如Google Chrome: 按F12查看开发者工具,然后点击上面的Application 重点来了,localStore在webview怎么用不了!! 原因是webView默认没有启动localStore功能的服务,需要我们自己手动去开启服务:
WebSettings settings = webview.getSettings(); settings.setDomStorageEnabled(true);localStore用法比较简单,就介绍到这里,下面讨论一下websql的使用:
Websql 是当前最多浏览器支持的本地数据库,可以说目前主流的浏览器都支持了,手机的WebView 也不例外(WebView使用Websql也需要开启服务,这点我们下面再说)。 Websql是一个轻量级的本地数据库,存储量达到几百万条数据以上,使用起来也是相当简单的,支持原生的sql语句(SELECT、INSERT、DELETE、UPDATE),下面简单介绍用法:
1)、打开websql数据库用函数openDatabase();
db = openDatabase(“数据库名”, "版本号", "数据库的描述信息", 数据库的大小);一个完整的例子:
var db = null; try { if (window.openDatabase) { db = openDatabase(“myDB”, "1.0", "Database example", 10*1024*1024); } catch(err) { db = null; alert("打开数据库失败"); }2)、创建表(注意,一切对表的操作都要使用事务),并且使用executeSql 函数
//executeSql函数有四个参数(第一个参数必填,后三个可以不写),函数原型如下: void executeSql(in DOMString sqlStatement, in optional ObjectArray arguments, in optional SQLStatementCallback callback, in optional SQLStatementErrorCallback errorCallback);参数意义分别: sqlStatement:是原生的sql语句。
例如:CREATE TABLE test (id, name)ObjectArray:上一句sql语句中的占位符“?”所对应的参数,空则写“[]”
例如:select name from student where id=?,[001]callback:本次sql操作成功后的回调接口,数据会被返回 errorCallback:本次sql操作失败后的回调接口,失败信息会被返回
创建一张test表:
db.transaction(function(tx) { tx.executeSql('CREATE TABLE test (id, name)'); });3)、插入(INSERT)操作
db.transaction(function (tx){ tx.executeSql("INSERT INTO test (id, name) VALUES ( ?, ?)", [001, “Biao”]); });4)、查询(SELECT)操作
db.transaction(function(tx) { tx.executeSql("SELECT * FROM test ", [], function(tx, result) { // result就是查询到的结果 }, function(tx, error) { alert('查询失败 ' + error.message); return; }); });5)、更新(UPDATE)操作
db.transaction(function (tx){ tx.executeSql("UPDATE test SET name = ? WHERE id = ?", [“wu”, 001]); });6)、删除(DELETE)操作
db.transaction(function(tx){ tx.executeSql("DELETE FROM test WHERE id = ?", [001]);});表创建成功之后同样也可以在web浏览器的开发者工具上看到数据(例如:谷歌浏览器)
以上就是Websql的四个主要操作了。
那么问题又来了,怎么Android Webview用不了Websql呢?
刚才已经说了,Websql是目前浏览器支持最为广泛的一个内置的本地数据库,没有之一,并且Android的Webview也已经支持了,但是,Webview默认是没有开启这个服务的,还是得我们自己开启,操作步骤如下:
WebSettings settings = webview.getSettings(); //设置与Js交互的权限 settings.setJavaScriptEnabled(true); //设置数据库可用 settings.setDatabaseEnabled(true); String dbPath = this.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); settings.setDatabasePath(dbPath); //然后 webview.setWebChromeClient(new MyChromeViewClient()); class MyChromeViewClient extends WebChromeClient { //重写这个方法就OK 了 @Override public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize, long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater){ //设置数据库存储大小 quotaUpdater.updateQuota(estimatedSize * 2); } }现在就可以在Webview上使用websql了
websql对数据的操作尽然不比localStore存储方便,但是这两个是没法比的,Websql存储数据是以一张张表的形式存在,存储量比localStore大多了。而且它对数据的操作还是我们相当熟悉的SQL语句。总而言之,方便好用。
但是!!大家有没有发现,我们再看看对数据的操作,全部得手写原生SQL语句!!SELECT INSERT UPDATE DELETE,当数据表的字段非常多的时候,所有字段都得我们自己去写入。不知道大家会不会觉得烦,反正我是烦了。
幸亏有IndexDB indexDB 支持本地存储大量对象,并使用健壮的数据访问机制检索数据。插入数据支持直接使用JSON数据,关键的是它不需要我们手写原生SQL语句来对数据进行查增删改。
下面简单介绍其用法 创建或者打开数据库
window.indexedDB.open(dbName, 1);参数意义: dbName:数据库的名称 1:版本号
1)、创建表
db.createObjectStore(tbName,{"keyPath":"keyID", autoIncrement:true});参数意义: tbName:表名称 {“keyPath”:”keyID”, autoIncrement:true}:设置字段keyid为主键,并且设置自动自增属性 可以添加字段,例如,添加name 字段 objectStore.createIndex(“name”, “name”,{unique:false}); 参数意义: “name”:字段名 “name”:设置字段name为索引,设置为索引后在查询的时候可以以name字段进行查询,加快查询速度。 {unique:false}:设置属性:不唯一。换句话说就是可以存在相同名字的数据
2)、插入数据(INSERT):
INDEXDB 和 WebSQL一样,对数据处理的时候要使用到事务
//获取事务 var transaction = database.transaction([tableName], model); //参数意义: //tableName:要操作的表名 //model:模式,有两种,readwrite(可读可写) 和readonly(只读) //获取表 var objectStore = transaction.objectStore(tableName); var request = objectStore.put(date); request.onerror = function(event) { alert("发生错误:" + request.error); }; request.onsuccess = function(event) { alert("数据保存成功"); };大家可以看到,上面没有出现字段名就完成对数据的插入了,上面的date是一个JS对象,只要把数据转换为JS对象数据就可以利用函数objectStore.put(date);插入数据了,其实也可以利用函数objectStore.add(date);插入数据。 如果是JSON 数据 可以利用$.parseJSON(data)来将JSON数据转成JS对象,然后对数据进行插入操作
put和add方法的区别在于,put插入数据的话
如果主键存在表中,那么就把旧数据更新 如果主键不存在表中,就插入一条新的数据。
add插入数据的话
如果主键存在表中,那么就会报错 如果主键不存在表中,就插入一条新的数据。
3)、查询数据(SELECT):
3.1)获取一条数据用函数get(key);
var transaction = database.transaction([tableName], model); var objectStore = transaction.objectStore(tableName); //key是主键的某一个值 var request = objectStore.get(key); request.onerror=function(e){ alert("发生错误:" + request.error); }; request.onsuccess=function(e){ var result=e.target.result; console.log("获取数据成功"); }3.2)获取所有数据用函数getAll();
var transaction = database.transaction([tableName], model); var objectStore = transaction.objectStore(tableName); var request = objectStore.getAll(); request.onerror=function(e){ alert("发生错误:" + request.error); }; request.onsuccess=function(e){ var result=e.target.result; console.log("获取数据成功"); }但是getAll()函数不推荐使用,貌似已经废弃了,反正我在平板Android4.4.2的webview上面不能使用。
3.3)推荐使用openCursor()利用游标的方式来进行查询多条数据,功能非常强大, 可以利用索引加快查询速度,还可以指定搜索的范围。
var transaction = database.transaction([tableName], model); var objectStore = transaction.objectStore(tableName); objectStore.openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { var rowData = cursor.value; for (var Key in rowData){ console.log("查询的数据"+Key[0]); } cursor.continue(); console.log(“1”); }else{ console.log(“2”); } }cursor.continue(); 表示,查询到了继续向前走,直至查询到所有结果截止。 注意,它和JAVA里面for循环的continue不一样,java的continue不会执行continue以后的语句,但是,cursor.continue();还是会执行以后的代码,例如上面的console.log(“1”);会一直被执行到。
但是!!
console.log(“2”);只会被执行一次,因为当cursor为空的时候,代表语句查询到所有结果了。
3.4)利用索引加快查询速度index(‘name’) name字段必须在一开始添加字段的时候给它设置为索引,如下:
objectStore.createIndex(“name”, “name”,{unique:false});
var transaction = database.transaction([tableName], model); var objectStore = transaction.objectStore(tableName); objectStore.index(‘name’).openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { var rowData = cursor.value; for (var Key in rowData){ console.log("查询的数据"+Key[0]); } cursor.continue(); console.log(“1”); }else{ console.log(“2”); } }3.5) 指定搜索的范围 使用到IDBKeyRange属性
Range Code //例如我上面指定主键是id , 意思就是查询id<=X的数据 //All keys ≤ x IDBKeyRange.upperBound(x) //查询id<X的数据 //All keys < x IDBKeyRange.upperBound(x, true) //查询id>=y的数据 //All keys ≥ y IDBKeyRange.lowerBound(y) //查询id>y的数据 //All keys > y IDBKeyRange.lowerBound(y, true) //All keys ≥ x && ≤ y IDBKeyRange.bound(x, y) //All keys > x &&< y IDBKeyRange.bound(x, y, true, true) //All keys > x && ≤ y IDBKeyRange.bound(x, y, true, false) //All keys ≥ x &&< y IDBKeyRange.bound(x, y, false, true) //查询id==z的数据 //The key = z IDBKeyRange.only(z) //查询id<=X的数据 var transaction = database.transaction([tableName], model); var objectStore = transaction.objectStore(tableName); objectStore.openCursor(IDBKeyRange.upperBound(x)).onsuccess = function(event) { var cursor = event.target.result; if (cursor) { var rowData = cursor.value; for (var Key in rowData){ console.log("查询的数据"+Key[0]); } cursor.continue(); console.log(“1”); }else{ console.log(“2”); } }3.6)删除数据《2017.7.10 更新》 删除数据,indexDB的操作很简单
/** * 删除数据 * */ function deleteData(tbName,value){ var objectStore = initDB(tbName,"readwrite"); var request=objectStore.delete(IDBKeyRange.only(parseInt(value))); request.onerror=function(e){ alert("发生错误:" + request.error); }; request.onsuccess=function(e){ var result=e.target.result; alert("删除数据成功"); } }注意:用delete()方法,传值一定得是创建表的index索引,否则删除失败,例如
objectStore = db.createObjectStore(personDoc,{"keyPath":"keyID", autoIncrement:true});上面的代码是指在创建表中指定索引为keyID ,是一个自增值,整型,因此index索引是一个数值,IDBKeyRange.only(parseInt(value))这个就表示只删除索引值为value值的数据。
以上简单介绍了IndexDB的部分用法,总体来说,indexDB的学习成本不高,但其实用性和方便性很强。需要深入学习的朋友可以去MDN(链接)学习。
怎么在Android 的 webview上使用,可以参考websql的设置,他们两个是一样的,当然在浏览器上面也是可以看到indexDB数据库存储的数据的。例如:谷歌浏览器
最后贴上一份indexDB 的样例代码
$(function(){ //全局数据库对象 var database; //数据库的名称 var dbName='HealDoc'; //数据表 var tbName='disease'; //表字段 var field="idcard/id/visitDate/visitWay/curSymptom/pressureH/pressureL/avoirdupois/bmi/arteriopalmus/smokeNum/drinkNum/trainingRate/trainingTime/rice/mentality/compiance/lastFbg/hgbde/hgbdedate/subCheck/dependence/sideEffects/effectsState/lowEffects/visitType/drugname/drugperday/drugpertime/drugname2/drugperday2/drugpertime2/drugname3/drugperday3/drugpertime3/insulin/insulinperday/insulinpertime/referralreason/referralagencies/nextDate/inputIdcard"; //创建数据库 var request = window.indexedDB.open(dbName, 1); request.onsuccess = function(event) { //让数据库 可在任何地方访问 database = request.result; }; request.onerror = function (event) { alert("发生错误:" + request.error); }; request.onupgradeneeded = function(event) { alert("第一次创建数据库或者更新数据库。"); db = request.result; //创建表 var objectStore = db.createObjectStore(tbName,{"keyPath":"keyID", autoIncrement:true}); var fields=new Array(); fields=field.split("/"); for (var i = 0; i < fields.length; i++) { objectStore.createIndex(fields[i],fields[i],{unique:false}); } } //对数据库处理得先初始化数据库 //参数一:表名 //参数二:操作数据库的模式 有两种:readwrite 和readonly function initDB(tableName,model){ //获取事务 var transaction = database.transaction([tableName], model); //获取表 var objectStore = transaction.objectStore(tableName); return objectStore; } function insert(date){ var objectStore=initDB("disease","readwrite"); //add 或者put var request = objectStore.put(date); request.onerror = function(event) { alert("发生错误:" + request.error); }; request.onsuccess = function(event) { alert("数据保存成功"); }; } function selectSingle(key){ var objectStore=initDB("disease","readonly"); var request=objectStore.get(key); request.onerror=function(e){ alert("发生错误:" + request.error); }; request.onsuccess=function(e){ var result=e.target.result; console.log(result); } } function selectAll(){ var objectStore = initDB("disease","readonly"); var response=""; // 打开游标,遍历customers中所有数据 objectStore.openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { var rowData = cursor.value; for (var Key in rowData){ response =response+Key+":"+rowData[Key]+"\n"; } response+="\n\n\n" cursor.continue(); } $('#output').val(response); } } $('#submitButton').click(function(){ var date = {}; var t = $('#yourformid').serializeArray(); // var str=""; $.each(t, function() { date[this.name] = this.value; // str+=this.name+"/" }); insert(date); return false; }); $('#close').click(function(){ selectAll(); }); });最后的最后,小弟不才,只能简述到这里了,如果有错误,请不吝赐教,如果有帮助到您的话,请留下一个start,O(∩_∩)O谢谢!