移动h5相关
程序员文章站
2022-04-13 17:33:42
...
Native调用js
js
<script type="text/javascript">
function readyToGo() {
console.log("111");
alert("Hello")
}
function alertMessage(message) {
alert(message)
}
function getYourCar(){
return "Car";
}
</script>
Native
//调用 js无参数,无返回值的函数
mWebView.loadUrl("javascript:readyToGo()");
//调用有参数、无返回值的函数
mWebView.loadUrl("javascript:alertMessage(\""+"content"+"\")")
//调用有返回值的番薯
mWebView.evaluateJavascript("getYourCar()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
//返回函数
Log.d(TAG, "onReceiveValue: "+s);
}
});
js调用native
- URL schema方式:
通过调用WebViewClient的shouldOverrideUrlLoading
如果没有设置WebviewClient,则会通知ActivitManager选择系统默认的浏览器进行处理,Given the host application a change to take over the control when a new url is about to be loaded in the current webview public boolean shouldOverrideUrlLoding(Webview webview,String url )
如果设置了WebviewClient,则会有app内部处理:
false:默认由Webview处理,webview.load(Url)
true:由native代码处理,- 拦截url跳转
return true:重写,自己处理,不交给webview处理,用来拦截webview的跳转或者自己处理问题。
return false:不处理,交由webview自己处理,默认情况 - 何时调用
- 网页内点击一个连接
- 用javascript location.href
- 但是代码中Webview.loadUrl不会回调
- tips:post请求不会回调该事件
- 拦截url跳转
- 在webview页面注入原始js代码,addJavaScriptInterface方法实现,
public class JavaBridge {
@JavascriptInterface
public String getUserInfo(){
return "user1";
}
}
....
mWebView.addJavascriptInterface(new JavaBridge(),"AndroidBridge");
...
function init(){
if(AndroidBridge){
console.log( AndroidBridge.getUserInfo());
}
}
- 4.2以下有安全漏洞,4.2以上修复@JavaScript.
4.2以下问题处理:WebChromeClient的jsPromp函数,将java的处理结果返回到js。
另外,在@javaScriptInterface注解的方法里,还可以在判断当前的加载的URL,来进行具体的请求:webview.getUrl() 主线程
@JavascriptInterface
public void showMessage(final String message) {
final Activity theActivity = this.activity;
final WebView theWebView = this.webView;
this.activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if(!theWebView.getUrl().startsWith("http://tutorials.jenkov.com")){
return ;
}
Toast toast = Toast.makeText(
theActivity.getApplicationContext(),
message,
Toast.LENGTH_SHORT);
toast.show();
}
});
}
- 重写 js里的 alert、prompt、console.log方法,
在WebviewChromeClient 里面实现回调,分别是:onJsAlert、onJsPrompt、onConsoleMessage
返回值:false(default),代表不处理,由webview处理;true:代表自己实现逻辑,webview不处理
Webview加载优化
- 资源本地化
将一些较重的资源本地化,不常更新的文件
存:打包时候,打入到apk中;
取:重写WebViewClient的WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)方法,通过一定的判别方法(例如正则表达式)拦截相应的请求,从本地读取相应资源并返回;默认返回null;
更:Cache Control,定期通过api更新本地资源。
WebSettings settings = webView.getSettings();
settings.setAppCacheEnabled(true);
settings.setDatabaseEnabled(true);
settings.setDomStorageEnabled(true);//开启DOM缓存
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
浏览器缓存
-
原理:http协议头,cache-control(Expires)Last-Modified
-
cache-control:控制文本在本地缓存的时间
- Expires字段:与Cache-Control功能相同,即控制缓存的有效时间
-
Last-Modified标志文件在服务器上的最新更新时间
缓存过期后,浏览器使用last-modified-since字段带上last-modified。服务器比较时间戳来判断文件是否有修改。没有修改返回304,继续使用缓存。否则200,返回最新文件
4.Etag,标识文件在服务器上的最新更新时间。Etag 的取值是一个对文件进行标识的特征字串
常见用法:* Cache-Control与 Last-Modified 一起使用 * Expires与 Etag一起使用;
-
Application Cache 缓存机制
- 以文件为单位进行缓存,且文件有一定更新机制
- AppCache 原理有两个关键点:manifest 属性和 manifest 文件
Dom Storage缓存机制
- localstorage key-value,持久性,清除浏览器缓存后localStorage会被删除,单个domin 5M限制
- sessionStorage 临时性,页面关闭后无法使用
Web SQL
IndexedDB
支持多种数据格式化,持久化存储、支持事务、游标、索引等数据库操作,空间大 50-250M
- 应用场景:LBS应用中,需要将latlng转化为地理位置,会通过高德api进行地理位置逆转码,返回一个比较大的json结构,可把他缓存下来,减少http请求,将latlng作为索引,
const $DB = {
init() {
let _this = this;
let req = indexedDB.open("hb_geocode");
req.onupgradeneeded = e => {
let db = req.result;
/*
createObjectStore 相当于创建一个表
"geo" 相当于表名
keyPath 索引 primary key
*/
let obStore = db.createObjectStore("geo", {
keyPath: "latlng"
});
// 下面这一段相当于创建表的一些数据结构
obStore.createIndex("address", "address", { unique: false });
obStore.createIndex("province", "province", { unique: false });
obStore.createIndex("district", "district", { unique: false });
obStore.createIndex("street", "street", { unique: false });
req.result.close();
};
},
/*
由于indexDB的操作为异步操作,因此用Promise对象进行包装 一下
*/
Add(payload) {
return new Promise((resolve, reject) => {
let db = indexedDB.open("hb_geocode");
/*
*/
db.onsuccess = () => {
db.result
.transaction("geo", "readwrite")
.objectStore("geo")
.add(payload);
db.result.close();
resolve();
};
db.onerror = e => {
reject(e);
};
});
},
Get(key) {
return new Promise((resolve, reject) => {
let db = indexedDB.open("hb_geocode");
db.onsuccess = () => {
let req = db.result
.transaction("geo", "readonly")
.objectStore("geo")
.get(key);
db.result.close();
req.onsuccess = e => {
resolve(e.target.result);
};
req.onerror = err => {
reject(err);
};
};
db.onerror = e => {
reject(e);
};
});
}
}
上一篇: redis作为mybatis的二级缓存
下一篇: 自动获得远程图片 #Writ