WebView特点:前端界面复用、动态更新、耗电、加载速度慢
WebView使用场景:用户协议(html排版)、广告页、新闻页
JS调用Java方法:网页视频播放
Java调用JS方法:夜间模式
Webview加载Html四种方式:
//加载URL
webView.loadUrl("http://139.196.35.30:8080/OkHttpTest/apppackage/test.html");
//加载asset文件夹下html页面
webView.loadUrl("file:///android_asset/test.html");
//加载手机sdcard上的html页面
webView.loadUrl("content://com.ansen.webview/sdcard/test.html");
//加载html代码
webView.loadDataWithBaseURL(null,"<html><head><title> 欢迎您 </title></head>" +
"<body><h2>使用webview显示 html代码</h2></body></html>", "text/html" , "utf-8", null);
WebViewClient主要帮助WebView处理各种通知、请求事件的,有以下常用方法:
- onPageFinished 页面请求完成
- onPageStarted 页面开始加载
- shouldOverrideUrlLoading URL拦截、自定义协议
- onReceivedError 访问错误时回调,例如访问网页时报错404,在这个方法回调的时候可以加载错误页面
WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等,有以下常用方法:
- onJsAlert webview不支持js的alert弹窗,需要自己监听然后通过dialog弹窗
- onReceivedTitle 获取网页标题
- onReceivedIcon 获取网页icon
- onProgressChanged 加载进度回调
返回键处理:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (webView.canGoBack() && keyCode == KeyEvent.KEYCODE_BACK) {
webView.goBack(); //goBack()表示返回webView的上一页面
return true;
}
return super.onKeyDown(keyCode, event);
}
WebView下载文件:
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition,
String mimetype, long contentLength) {
//自己下载文件
new HttpThread(url).start();
//通过系统下载文件
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
错误页面处理:
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
//加载本地错误页面
view.loadUrl("file:///android_asset/error.html");
//展示native页面
mTextView_Error.setText("404");
view.setVisibility(View.GONE);
}
设置Cookie:
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.setCookie("https://www.baidu.com", "cookie info");
js调用Java方法(三部曲):允许WebView加载js、编写js接口类、添加js本地映射
mWebView.getSettings().setJavaScriptEnabled(true);//开启JS交互
mWebView.addJavaScriptInterface(new WebHost(context), "jsBridge");//JS本地映射
public class WebHost {
public Context mContext;
public WebHost(Context context) {
mContext = context;
}
//方法必须是public的
//该方法不在主线程执行,需要handler更新界面
@JavascriptInterface
public void callJs() {
Toast.makeText(mContext, "call from js", Toast.LENGTH_LONG).show;
}
}
对应js代码:jsBridge.callJs();
需要处理混淆:
-keep public class com.example.webview.WebHost {
public <methods>;
}
Java调用js方法:
String str = mEditText.getText().toString();
mWebView.loadUrl("javascript:if(window.remote){window.remote(str)}");
//对应html中的js代码
var remote = function (str) {
}
WebView常见的一些坑:
- 安全漏洞:Android API 17之前由于WebView.addJavascriptInterface方法存在安全漏洞,js代码可以通过Java Reflection API执行任意的Java对象的方法
- 内存泄漏问题:动态添加的WebView,需要先removeView方法,然后调用WebView的removeAllView和destory方法
- WebViewClient.onPageFinished在网页跳转时会被调用多次,可以使用WebChromeClient.onProgressChanged
- 后台耗电:WebView会自动开启线程,需要在Activity的onDestory中销毁WebView
- 硬件加速(Android 3.0之后):会出现页面白块问题,解决方法是关闭硬件加速
WebView内存泄漏:创建WebView需要传入Activity(动态创建WebView,传入ApplicationContext某些时候会报错),造成内存泄漏的原因是,WebView在执行onDetachedFromWindow时会判断WebView当前状态,如果已经销毁了,则直接返回,不执行反注册逻辑
if (isDestroyed()) return;,
解决办法有:
独立进程(用完结束进程)
让onDetachedFromWindow先走,在主动调用destroy()之前,把webview从它的parent上面移除掉
ViewParent parent = mWebView.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(mWebView);
}
mWebView.removeAllViews();
mWebView.destroy();
WebView相关方法:reload、canGoBack、goBack、setWebChromeClient、setWebViewClient、setCacheMode、addJavaScriptInterface、setJavaScriptEnabled、setDownloadListener
在WebviewClient的onPageFinished中调用js代码获取图片的位置信息,然后动态更改ImageView大小和显示位置
HybridCache旨在提供一种native和webview之间共享缓存的解决方案,尤其是共享native中的图片缓存