前言

当用户浏览页面时,快速的页面加载速度对用户体会至关重要。而在运用中运用WebView展现页面时,缓慢的加载速度也会直接影响到用户的体会。针对WebView渲染速度和加载速度慢的问题,大局缓存池办理技能应运而生。

本文将介绍大局缓存池技能在运用WebView加载网页中的运用,经过本文,你将了解到怎么运用大局缓存池办理技能来大幅进步WebView的加载速度,防止用户长时间的等候,从而为用户带来更好的运用体会。

效果图

直接上图,便利咱们直观上看出优化后的效果

WebView组件封装(一)——怎样使用全局缓存池管理提高WebView加载速度

WebView组件封装(一)——怎样使用全局缓存池管理提高WebView加载速度

大局WebView的好处

  1. 简化开发:运用大局WebView无需在多个Activity或Fragment中重复定义WebView,大大削减代码量,进步开发功率
  2. 一致性:大局WebView一致了运用内的WebView样式和行为,保证了用户体会的一致性,添加用户粘性
  3. 优化性能:多个WebView的情况下,每个WebView都需求占用必定的内存和CPU,而运用大局WebView能够削减这种资源浪费,从而优化运用的性能
  4. 便利保护:在多个WebView的情况下,每个WebView的保护和更新都需求额外的工作,而运用大局WebView只需求在一个当地进行保护和更新即可,便利快捷

创立大局缓存池办理WebView

一、在Application的时分,创立一个WebView的缓存池,缓存池存放3个WebView的实例
     private lateinit var mWebViewPool: Array<PkWebView?>
     val WEB_VIEW_COUNT = 3
    /**
     * 初始化WebView池
     */
    fun initWebViewPool(context: Context?, userAgent: String = "") {
        mWebViewPool = arrayOfNulls(WEB_VIEW_COUNT)
        if (context == null) return
        for (i in 0 until WEB_VIEW_COUNT) {
            mWebViewPool[i] = createWebView(context, userAgent)
        }
    }
    private fun createWebView(context: Context, userAgent: String): PkWebView? {
        val webView = PkWebView(context)
        //初始化WebView的参数等
        WebViewManager.instance.apply {
            initWebViewSetting(webView, userAgent)
            initWebChromeClient(webView)
            initWebClient(webView)
        }
        return webView
    }
  • 上面一共创立了3个WebView,createWebView 函数用于创立一个新的 WebView 目标,并初始化 WebView 的相关参数和配置
  • 这儿将userAgent供给出去,由于不同的项目或许UserAgent值纷歧样,这儿需求留意webSettings.getUserAgentString()会获取到手机型号、浏览器版别和操作系统版别等信息
二、获取WebView目标
    /**
     * 获取webView
     */
    fun getWebView(): PkWebView? {
        checkIsInitialized()
        for (i in 0 until WEB_VIEW_COUNT) {
            if (mWebViewPool[i] != null) {
                val webView = mWebViewPool[i]
                mWebViewPool[i] = null
                return webView
            }
        }
        return null
    }
    private fun checkIsInitialized() {
        if (!::mWebViewPool.isInitialized) {
            throw UninitializedPropertyAccessException("Please call the PkWebViewInit.init method for initialization in the Application")
        }
    }

这儿咱们或许会有疑问,为什么是3个Fragment? 假定ViewPager中有三个WebView 的Fragment,没有做懒加载的时分,首页第一次直接切到第二个Fragment,那这三个Fragment都会被初始化,也就是或许会消耗3个WebView

这儿将mWebViewPool[i]=null,起到的是标识效果

三、毁掉webView目标
    /**
     * Activity毁掉时需求开释当时WebView
     */
    fun releaseWebView(webView: PkWebView?) {
        checkIsInitialized()
        webView?.apply {
            stopLoading()
            removeAllViews()
            clearHistory()
            destroy()
            (parent as ViewGroup?)?.removeView(this)
            for (i in 0 until WEB_VIEW_COUNT) {
                if (mWebViewPool[i] == null) {
                    mWebViewPool[i] = webView
                    return
                }
            }
        }
    }

运用很简单我就不细说了,releaseWebView是在Fragment/Activity的onDestroy中进行调用,这儿需求留意,还需求将取得的WebView在onDestroy中设置为null

    override fun onDestroy() {
        WebViewPool.instance.releaseWebView(mWebView)
        mWebView = null
        super.onDestroy()
    }

当咱们第一次运转的时分,一切都是ok的,也明显速度变快了。可是当咱们点击退出,再次进入的时分,显现一片空白,这是为什么呢? 这是由于咱们在onDestroy的时分调用了webView的destroy()办法

那么webView的destory()办法做了哪些工作呢? Android渠道版别的不同,WebView毁掉的效果或许也有所不同。通常情况下,WebView在毁掉时会做以下三件工作

  1. WebViewClient和WebViewChromeClient的引证免除:WebView中的WebViewClient和WebViewChromeClient这两个类或许会引证当时Activity或Fragment,假如在WebView毁掉时没有将这两个类引证免除,就有或许出现内存泄漏的问题

  2. 所有异步任务的取消:WebView中有很多异步任务,例如图片加载、javaScript执行等等。在毁掉WebView时,需求将这些任务取消,防止出现线程泄漏的问题

  3. WebView相关组件和线程的毁掉:WebView内部包含了很多组件和线程,例如:WebViewCore、JavaScriptCore、WebViewWorker等等

WebView的destory()不必定能够彻底毁掉WebView,由于WebView内部或许存在一些难以办理和追踪的资源和线程,例如JavaScript执行线程、标准库线程等等,所以在运用WebView的时分,咱们需求及时开释WebView目标

怎么处理webView.destroy()之后再次启动的时分显现空白问题呢?

  • 1.不调用WebView的destory()?也能够正常运转,可是资源没法开释
  • 2、既然还要destroy,那destory之后,再从头设置WebViewClient、WebChromeClient这些参数呢?其实也不可行哈。由于此刻调用完之后webView目标已无法再次运用,WebView所占用的资源都被开释了,而且WebView目标不再关联任何的Activity或Fragment
  • 3、从头创立WebView,并设置WebViewClient、WebChromeClient这些参数,这样是能够的。
    fun releaseWebView(webView: PkWebView?) {
        checkIsInitialized()
        webView?.apply {
            stopLoading()
            removeAllViews()
            clearHistory()
            destroy()
            (parent as ViewGroup?)?.removeView(this)
            for (i in 0 until WEB_VIEW_COUNT) {
                if (mWebViewPool[i] == null) {
                    mWebViewPool[i] = createWebView(webView.context,mUserAgent)
                    return
                }
            }
        }
    }

总结

该文章介绍了大局缓存池办理技能在运用 WebView 加载网页中的运用。经过该技能的实现,咱们能够极大地进步 WebView 加载网页的速度,让用户取得更好的运用体会。假如你对该技能或者本文有任何问题和定见,能够前往本项目的 Github 地址github.com/Peakmain/Pk…进行讨论和沟通。

大局WebView缓存池的源码方位:WebViewPool.kt