WebView的基础使用跟一些坑的集思录(后续碰到坑会继续添加)
2019-11-20 本文已影响0人
未扬帆的小船
一、前言:
本篇文章只是记录一下webview使用过程的基本用法跟自己碰到的一点坑,如果想看很完整版之类的可以看一下下面其他大神的几个文章:
Android WebView 详解
史上最全WebView使用,附送Html5Activity一份
Android WebView:这是一份 详细 & 易懂的WebView学习攻略(含与JS交互、缓存构建等)
(=_=!前面先说一下 免得浪费大家宝贵的时间)
二、简介
基于webkit引擎展现web页面的控件高低版本实现不同
- Android 4.4前:各个安卓版本使用了不同的webkit版本的内核
- Android 4.4后:使用了Chrome内核
三、相关基础类
webView相关类的大意图.png详情请看:Android WebView 详解 ,里面有很多常用api的中文注释
四、基础使用:
- 在布局文件中直接放入
<WebView>
webView = findViewById(R.id.web)
- 在代码中添加
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mWebView = new WebView(getApplicationContext());
mWebView.setLayoutParams(params);
mLayout.addView(mWebView);
最基础的配置信息
val webSettings = webView.settings
webSettings.javaScriptEnabled = true //支持js
webView.webViewClient = object :WebViewClient(){
//下面两种写法都可以让url在我们的webview中执行,而不会跳到系统的浏览器
// override fun shouldOverrideUrlLoading( view: WebView?, request: WebResourceRequest?): Boolean {
// view!!.loadUrl(request!!.url.toString())
// return true
// }
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
return super.shouldOverrideUrlLoading(view, request)
}
}
//加载url webView.loadUrl("https://www.baidu.com")
ok,上面过后就可以简单的使用了。
后面讲一下第二种方式的添加WebView的好处,看后面的 内存泄漏处理
五、 本地加载文件
- 在android文件中assets目录下放相应的*.html文件
- 代码上调用
mWebView.loadUrl("file:///android_asset/相应的文件名.html")
ok 这样子就可以加载本地的文件了
六、与js交互
android、js交互几个种方式.png一定要先添加下面语句,启用Javascript
settings.setJavaScriptEnabled(true);
1. Andorid调用js
1.1 android执行js表达式
// 弹出提示框
web.loadUrl("javascript:alert('hello')");
// 调用注入的jsobj.say方法
web.loadUrl("javascript:jsobj.say('hello')");
1.2 在API19后可异步执行JS表达式,并通过回调返回值
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
vWeb.evaluateJavascript("你好~", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
}
});
}
2. Js调用Android
2.1 注入对象到Javascript
//调用
web.addJavascriptInterface(new JsObject(), "TestObject")
//增加JsObject类
class JsObject{
@JavascriptInterface
fun javacalljs(){
Toast.makeText(this@CenterSystemFragment.context,"成功回调安卓",Toast.LENGTH_SHORT).show()
}
@JavascriptInterface
fun javacalljswithargs(arg:String){
Toast.makeText(this@CenterSystemFragment.context,"成功回调安卓$arg",Toast.LENGTH_SHORT).show()
}
}
2.2 在WebViewClient#sholudOveriideUrlLoading()
拦截
webViewClient = object : WebViewClient() {
//在网页上的所有加载都经过这个方法,这个函数我们可以做很多操作,
//比如截取url的参数然后去做逻辑操作
override fun shouldOverrideUrlLoading(view:WebView?,request: WebResourceRequest?): Boolean {
view!!.loadUrl(request!!.url.toString())
return true
}
}
2.3 WebChromeClient# onJsAlert() onJsPrompt()
等方法拦截js对话框
mWebChromeClient = object : WebChromeClient() {
override fun onJsPrompt(
view: WebView?,
url: String?,
message: String?,
defaultValue: String?,
result: JsPromptResult?
): Boolean {
return super.onJsPrompt(view, url, message, defaultValue, result)
}
override fun onJsConfirm(
view: WebView?,
url: String?,
message: String?,
result: JsResult?
): Boolean {
return super.onJsConfirm(view, url, message, result)
}
override fun onJsAlert(
view: WebView?,
url: String?,
message: String?,
result: JsResult?
): Boolean {
return super.onJsAlert(view, url, message, result)
}
}
七 填坑纪实
1. 内存泄漏
- 在代码中添加
webView
并传入application context
不挟持activity
可以处理很大一部分的内存泄漏,就是本篇文章开头基础使用的第二种用法。 - 销毁WebView
if (vWeb != null) {
vWeb.setWebViewClient(null);
vWeb.setWebChromeClient(null);
vWeb.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
vWeb.clearHistory();
((ViewGroup) vWeb.getParent()).removeView(vWeb);
vWeb.destroy();
vWeb = null;
}
2. Error inflating class android.webkit.WebView
可以看下其它网友的处理方法 https://blog.csdn.net/qq_36347817/article/details/86625447
如果是androidx 5.0 系统 webview闪退报这种问题问题的话,可以尝试一下下面的解决方案,具体我也没搞懂是怎么一回事,如果有懂的同学麻烦说一下
public class LollipopFixedWebView extends WebView {
public LollipopFixedWebView(Context context) {
super(getFixedContext(context));
}
public LollipopFixedWebView(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
}
public static Context getFixedContext(Context context) {
return context.createConfigurationContext(new Configuration());
}
}