当前位置:   article > 正文

Android:WebView使用常见问题汇总(持续更新)_androidx webkit

androidx webkit

前言

从事Android以来,几乎离不开WebView的使用。但是使用WebView的过程中,总会出一些令人意想不到的问题,故打算写一篇文章专门用来记录开发过程中遇到的问题吧。如果大家有遇到什么奇怪的问题,欢迎补充完善。

WebView多语言如何处理字体反向

通过改变html dir的属性即可改变文字的方向,比如设置dir="RTL"则表示文字从右往左;

比如: <html dir=\"rtl\" lang=\"\"><body>" + outhtml + "</body></html>

而默认不设置的话,则是从左往右的。

所以如果要对不同的语言进行文字方向适配的话就需要客户端判断当前语言环境下的文字方向了,然后去调整html的文字方向。

而客户端如何判断当前语言文字的方向呢?我直接把代码放到下面了

		if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL){
            //代表文字从右往左
        }else{
         	//文字方向从左往右   
        }
  • 1
  • 2
  • 3
  • 4
  • 5

接下来对应调整html的方向了,但是此时分为两种情况。

  1. 直接通过loadDataWithBaseURL加载html代码。
  2. 通过loadUrl直接加载前端URL

第一种比较好解决,直接客户端判断然后手动注入dir="RTL"即可,比如:

		if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL){
            desc.loadDataWithBaseURL(bull, "<html dir=\"rtl\" lang=\"\"><body>" + outhtml + "</body></html>", "text/html", "UTF-8", null);
        }else{
         	desc.loadDataWithBaseURL(bull, outHtml, "UTF-8", null);
        }
  • 1
  • 2
  • 3
  • 4
  • 5

第二种这里目前本人没有遇到过,但是无非就是需要通知到html当前文字方向而已,然后他们自己可以根据当前的文字方向去做处理就可以。至于如何通知到html。这个可以和html的研发同学约定,通过JavascriptInterface的方式进行交互即可。这里不再深入展开。

WebView如何适配暗黑模式

这一块再Android10以上Google官方有给出解决方案。利用WebSettingsCompat可以进行设置处理。

怎么使用呢?

首先,引入webkit库。

implementation "androidx.webkit:webkit:1.4.0"
  • 1

然后再WebView初始化的时候放入如下的代码即可

kotlin版本

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
        Configuration.UI_MODE_NIGHT_YES -> {
            WebSettingsCompat.setForceDark(myWebView.settings, FORCE_DARK_ON)
        }
        Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> {
            WebSettingsCompat.setForceDark(myWebView.settings, FORCE_DARK_OFF)
        }
        else -> {}
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

java版本

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
        case Configuration.UI_MODE_NIGHT_YES:
            WebSettingsCompat.setForceDark(myWebView.getSettings(), FORCE_DARK_ON);
            break;
        case Configuration.UI_MODE_NIGHT_NO:
        case Configuration.UI_MODE_NIGHT_UNDEFINED:
            WebSettingsCompat.setForceDark(myWebView.getSettings(), FORCE_DARK_OFF);
            break;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

更多的使用方式可以参考:Draken web content.

WebView 预加载、对象缓存实现

我们知道对于WebView加载优化来说,有一个很重要优化策略就是WebView的预加载以及对象的缓存,因为WebView过于沉重,导致再构建是耗时比较久。为避免使用时再构建,可以增加预加载以及WebView对象复用。

下面直接放WebView预加载以及复用池工具类,可以直接使用。

class WebViewPool {

    private val webViewCache: MutableList<WebView> = ArrayList(NUM)

    fun prepare(context: Context) {
        if (webViewCache.isEmpty()) {
            Looper.myQueue().addIdleHandler {
                webViewCache.add(create(MutableContextWrapper(context)))
                false
            }
        }
    }

    fun get(context: Context): WebView {
        if (webViewCache.isEmpty()) {
            webViewCache.add(create(MutableContextWrapper(context)))
        }
        return webViewCache.removeFirst().apply {
            val contextWrapper = context as MutableContextWrapper
            contextWrapper.baseContext = context
            clearHistory()
            resumeTimers()
        }
    }

    fun recycle(webView: WebView) {
        try {
            with(webView){
                stopLoading()
                loadDataWithBaseURL(null, "", "text/html", "utf-8", null)
                clearHistory()
                pauseTimers()
                webChromeClient = null
                webViewClient = WebViewClient()
            }
            val parent = webView.parent
            if (parent != null) {
                (parent as ViewGroup).removeView(webView)
            }
        } catch (e: Exception) {
        } finally {
            if (!webViewCache.contains(webView)) {
                webViewCache.add(webView)
            }
        }
    }

    fun destroy() {
        try {
            webViewCache.removeAll {
                it.removeAllViews()
                it.destroy()
                false
            }
        } catch (e: Exception) {
        }
    }

    private fun create(context: Context) = WebView(context)

    companion object{
        const val NUM = 1
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

WebView如何处理跨域问题

何为跨域?

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

怎么处理呢?

  • 设置webviewsettingallowUniversalAccessFromFileURLs、为true

    settings.allowUniversalAccessFromFileURLs = true
    
    • 1
  • 如果上述设置还是跨域,那么是不是本来需要网络请求的资源你缓存到本地加载了呢?如果是,则可以直接做如下的设置:

    webResourceResponse.responseHeaders = mapOf(
                            "Access-Control-Allow-Origin" to "*",
                            "Access-Control-Allow-Headers" to "*",
                            "Access-Control-Allow-Credentials" to "true",
                            "Access-Control-Allow-Methods" to "POST, PUT, GET, OPTIONS, DELETE"
                            )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

注意:如果设置了可以无限制跨域,从安全层面来说,需要对文件做校验处理,对js调用做鉴权处理。

持续更新…

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/196571
推荐阅读