WebView白屏优化的一些整理

WebView打开出现白屏和速度慢的一些原因:

1.H5页面运行在独立进程中,H5打开需要首先启动Web进程。

 

2.每次关闭H5页面会通过exitProcess(0)关闭Web 进程。

优化方案:

1.Web进程预启动。

通过绑定服务的方式启动一个Service来对WebView进程进行预热。

<service
            android:name=".service.PreWebService"
            android:enabled="true"
            android:process=":Webview"
            android:exported="true">
        </service>
class PreWebService : Service() {

    override fun onBind(intent: Intent): IBinder? {
        return null
    }
}

 

val intent = Intent(context, PreWebService::class.java)
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
 private val mConnection =

        object : ServiceConnection {
            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                mBound = true
            }

            override fun onServiceDisconnected(name: ComponentName?) {
                mBound = false
            }

        }

 

if (mBound) {
	context.unbindService(mConnection)
	mBound = false
}


2.WebView 预创建与复用。

class WebViewManager private constructor() {
    companion object {
        @Volatile
        private var INSTANCE: WebViewManager? = null

        private fun instance() = INSTANCE ?: synchronized(this) {
            INSTANCE ?: WebViewManager().also {
                INSTANCE = it
            }
        }

        fun prepare(context: Context) {
            instance().prepare(context)
        }

        fun obtain(context: Context): WebView {
            return instance().obtain(context)
        }

        fun recycle(webView: WebView) {
            instance().recycle(webView)
        }

        fun destroy(context: Context) {
            instance().destroy(context)
        }

        fun goBack(webView: WebView, originalUrl: String): Boolean {
            val canBack = webView.canGoBack()
            if (canBack) webView.goBack()
            val backForwardList = webView.copyBackForwardList()
            val currentIndex = backForwardList.currentIndex
            if (currentIndex == 0) {
                val currentUrl = backForwardList.currentItem?.url
                val currentHost = Uri.parse(currentUrl).host
                //栈底不是链接则直接返回
                if (currentHost.isNullOrBlank()) return false
                //栈底链接不是原始链接则直接返回
                if (originalUrl != currentUrl) return false
            }
            return canBack
        }
    }

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

    private var mBound = false

    fun prepare(context: Context) {
        if (webViewCache.isEmpty()) {
            Looper.myQueue().addIdleHandler {
                webViewCache.add(create(MutableContextWrapper(context)))
                val intent = Intent(context, PreWebService::class.java)
                context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
                false
            }
        }
    }

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

    fun recycle(webView: WebView) {
        try {
            webView.stopLoading()
            webView.loadDataWithBaseURL("about:blank", "", "text/html", "utf-8", null)
            webView.clearHistory()
            webView.pauseTimers()
            val parent = webView.parent
            if (parent != null) {
                (parent as ViewGroup).removeView(webView)
            }
            val contextWrapper = webView.context as MutableContextWrapper
            contextWrapper.baseContext = webView.context.applicationContext
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            if (!webViewCache.contains(webView)) {
                webViewCache.add(webView)
            }
        }
    }

    fun destroy(context: Context) {
        try {
            if (mBound) {
                context.unbindService(mConnection)
                mBound = false
            }
            webViewCache.forEach {
                it.removeAllViews()
                it.destroy()
                webViewCache.remove(it)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun create(context: Context): WebView {
        return WebView(context)
    }

    private val mConnection =

        object : ServiceConnection {
            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                mBound = true
            }

            override fun onServiceDisconnected(name: ComponentName?) {
                mBound = false
            }

        }
}

 

3.WebView页面关闭时不关闭Web进程,只做资源清理。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值