前言
当用户浏览页面时,快速的页面加载速度对用户体会至关重要。而在运用中运用WebView展现页面时,缓慢的加载速度也会直接影响到用户的体会。针对WebView渲染速度和加载速度慢的问题,大局缓存池办理技能应运而生。
本文将介绍大局缓存池技能在运用WebView加载网页中的运用,经过本文,你将了解到怎么运用大局缓存池办理技能来大幅进步WebView的加载速度,防止用户长时间的等候,从而为用户带来更好的运用体会。
效果图
直接上图,便利咱们直观上看出优化后的效果
大局WebView的好处
- 简化开发:运用大局WebView无需在多个Activity或Fragment中重复定义WebView,大大削减代码量,进步开发功率
- 一致性:大局WebView一致了运用内的WebView样式和行为,保证了用户体会的一致性,添加用户粘性
- 优化性能:多个WebView的情况下,每个WebView都需求占用必定的内存和CPU,而运用大局WebView能够削减这种资源浪费,从而优化运用的性能
- 便利保护:在多个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在毁掉时会做以下三件工作
-
WebViewClient和WebViewChromeClient的引证免除:WebView中的WebViewClient和WebViewChromeClient这两个类或许会引证当时Activity或Fragment,假如在WebView毁掉时没有将这两个类引证免除,就有或许出现内存泄漏的问题
-
所有异步任务的取消:WebView中有很多异步任务,例如图片加载、javaScript执行等等。在毁掉WebView时,需求将这些任务取消,防止出现线程泄漏的问题
-
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