WebView的基础使用跟一些坑的集思录(后续碰到坑会继续添加)

2019-11-20  本文已影响0人  未扬帆的小船

一、前言:

本篇文章只是记录一下webview使用过程的基本用法跟自己碰到的一点坑,如果想看很完整版之类的可以看一下下面其他大神的几个文章:
Android WebView 详解
史上最全WebView使用,附送Html5Activity一份
Android WebView:这是一份 详细 & 易懂的WebView学习攻略(含与JS交互、缓存构建等)

(=_=!前面先说一下 免得浪费大家宝贵的时间)

二、简介

基于webkit引擎展现web页面的控件高低版本实现不同

三、相关基础类

webView相关类的大意图.png
详情请看:Android WebView 详解 ,里面有很多常用api的中文注释

四、基础使用:

  1. 在布局文件中直接放入<WebView>
webView = findViewById(R.id.web)
  1. 在代码中添加
        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的好处,看后面的 内存泄漏处理

五、 本地加载文件

  1. 在android文件中assets目录下放相应的*.html文件
  2. 代码上调用
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. 内存泄漏

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());
    }
}
上一篇下一篇

猜你喜欢

热点阅读