WebView开发小记.

最近重构了公司的播放器模块,重新整理了整套代码,并且加入了StateMachine, 然后现在处于提测阶段, 打算在提测确认无bug之后进行一次StateMachine使用的总结,在这个任务空档期,老大安排了我去搞一下公司的WebView模块, 也算是换换脑子.

该文章记录一下几个在开发过程中的小经验

  • 当你使用WebView加载网页的时候, 如果这个网页有JavaScript, 你要跟它进行交互的话,你需要打开开关.

    1
    WebView.getSetting.setJavaScriptEnabled(true);
  • Java与JavaScript 交互比较关键的一个方法是

    1
    WebView.addJavascriptInterface(Object, String);

    这个方法简单的来说
    就是往JavaScript 注入一个可以供他们使用,进行回调的Object, String 就是 这个Object的名字.
    举例来说:
    比如 我们在Java代码中 写了这样一段代码

    1
    2
    3
    4
    5
    6
    WebView.addJavascriptInterface(new Object(){
    @JavascriptInterface
    public void inject() {
    Log.d(TAG, "Inject success");
    }
    }, "InjectObject");

    而在Javascript中 代码如下

    1
    InjectObject.inject("hi, i'm Javascript");

    这样Java中就可以回调打印出Inject success的字段.
    这里需要特殊说明的一点就是 addJavascriptInterface的Object 中必须有一个方法是声明 @JavascriptInterface 的, 否则是无法add进去的.
    并且只有声明了 @JavascriptInterface 的方法 才能被JavaScript 成功调用.

  • Java 和 Javascript 交互的本质是字符串的传递.
    Java 无论你上层如何封装, 最终将字符串从Java 传到Javascript 都是需要这样去传递的.
    1
    WebView.loadUrl("javascript:WebViewJavascriptBridge._handleMessageFromJava('%s')")

其中 javascript: 是必须的. WebViewJavascriptBridge 是Javascript那边的对象,_handleMessageFromJava 是这个对象所拥有的方法. ()内就是要传递过去的字符串!
这里有一点需要注意, loadUrl方法会进行checkThread(); 所以也就是说你必须在MainThread中调用该方法.

  • WebView 有内存泄漏的问题, 属于系统代码的1个bug, 在这里我们做了特殊的 WorkAround.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    private void recycle() {
    try {
    MagicWebView thiz = this;
    thiz.setWebViewClient(null);
    thiz.setWebChromeClient(null);

    Field field = View.class.getDeclaredField("mContext");
    field.setAccessible(true);
    field.set(thiz, getContext().getApplicationContext());
    field.setAccessible(false);
    field = View.class.getDeclaredField("mParent");
    field.setAccessible(true);
    field.set(thiz, null);
    field.setAccessible(false);
    field = View.class.getDeclaredField("mLayoutParams");
    field.setAccessible(true);
    field.set(thiz, null);
    field.setAccessible(false);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

这样并不能完全解决WebView 会泄露的问题, WebView 依旧会被泄露, 但是WebView跟相应的Activity 会完全解耦,
不会造成Activity也跟着泄露.

  • 在Https的网址下,有的H5图片会加载不正常. 这个时候需要加入这样一个设置
    1
    2
    3
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
    }
Share Comments