从事Android以来,几乎离不开
WebView的使用。但是使用WebView的过程中,总会出一些令人意想不到的问题,故打算写一篇文章专门用来记录开发过程中遇到的问题吧。如果大家有遇到什么奇怪的问题,欢迎补充完善。
通过改变html dir的属性即可改变文字的方向,比如设置dir="RTL"则表示文字从右往左;
比如: " + outhtml + "。
而默认不设置的话,则是从左往右的。
所以如果要对不同的语言进行文字方向适配的话就需要客户端判断当前语言环境下的文字方向了,然后去调整html的文字方向。
而客户端如何判断当前语言文字的方向呢?我直接把代码放到下面了
if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL){
//代表文字从右往左
}else{
//文字方向从左往右
}
接下来对应调整html的方向了,但是此时分为两种情况。
loadDataWithBaseURL加载html代码。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);
}
第二种这里目前本人没有遇到过,但是无非就是需要通知到html当前文字方向而已,然后他们自己可以根据当前的文字方向去做处理就可以。至于如何通知到html。这个可以和html的研发同学约定,通过JavascriptInterface的方式进行交互即可。这里不再深入展开。
这一块再Android10以上Google官方有给出解决方案。利用WebSettingsCompat可以进行设置处理。
怎么使用呢?
首先,引入webkit库。
implementation "androidx.webkit:webkit:1.4.0"
然后再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 -> {}
}
}
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;
}
}
更多的使用方式可以参考:Draken web content.
我们知道对于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
}
}
何为跨域?
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
怎么处理呢?
设置webview的setting 的allowUniversalAccessFromFileURLs、为true。
settings.allowUniversalAccessFromFileURLs = true
如果上述设置还是跨域,那么是不是本来需要网络请求的资源你缓存到本地加载了呢?如果是,则可以直接做如下的设置:
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"
)
注意:如果设置了可以无限制跨域,从安全层面来说,需要对文件做校验处理,对js调用做鉴权处理。
持续更新…
🙆♀️。欢迎技术探讨噢!