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


    前言

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

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

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

    比如: " + outhtml + "

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

    所以如果要对不同的语言进行文字方向适配的话就需要客户端判断当前语言环境下的文字方向了,然后去调整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, "" + outhtml + "", "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调用做鉴权处理。

    持续更新…
    🙆‍♀️。欢迎技术探讨噢!

  • 相关阅读:
    Spring Boot AOP 扫盲,实现接口访问的统一日志记录
    Qwt开发笔记(二):Qwt基础框架介绍、折线图介绍、折线图Demo以及代码详解
    大众集团「换舵手」,软件战略从「自研优先」转向开放协作
    一种基于折射反向学习机制与自适应控制因子的改进樽海鞘群算法 -附代码
    CM72 另类加法
    打印请求头
    AI伦理专家:引领人工智能时代的道德导航者
    JUL 日志
    Echarts数据分析系统Data Analysis Platform使用说明文档
    比亚迪高端化火急提速
  • 原文地址:https://blog.csdn.net/weixin_44235109/article/details/126572828