Android产品研发(十八)--webview问题集锦

Android产品研发(⼗⼋)--webview问题集锦转载请标明出处:
上⼀篇⽂章中我们介绍了hybrid开发相关的知识。重点介绍了hybrid开发的概念,hybrid开发的作⽤,Android中如何实现hybrid开
发,Android中实现hybrid开发的例⼦,以及产品开发中hybrid开发实践等,通过对以上这些概念的介绍我们对hybrid开发应该已经有了⼤概的了解,更多具体的内容可参考我的:
本⽂中我们将介绍⼀下Android中webview在使⽤过程中会遇到的⼀些问题。这些问题主要是webview在使⽤过程中我已经趟过的坑,希望通过这篇⽂章的介绍能够帮助⼤家更好的使⽤webview。
下⾯是本⽂主要介绍的⼀些知识点,后续使⽤过程中可能会有更新。
webview的性能优化
webview注⼊cookie信息
webview退出activity异常
webview中native与js交互
webview下载⽂件
腾讯X5浏览服务
最近App中相当⼀部分的页⾯内容使⽤的是webview。⽽使⽤webview加载页⾯⼀个需要注意的地⽅就是性能,所以最近也研究了⼀下webview的性能优化问题。
webview的性能问题
在讲解webview的性能问题之前,我们先来了解⼀下Android webview的缓存机制。
Android WebView缓存机制
WebView中存在着两种缓存:⽹页数据缓存(⽹页数据,url等)、H5缓存(H5代码缓存数据)
不同的缓存数据会保存在不同的⽂件⽬录下,这⾥引⽤⼀下其他blog的说法:
当我们加载Html时候,会在我们data/应⽤package下⽣成database与cache两个⽂件夹:
我们请求的Url记录是保存在webviewCache.db⾥,⽽url的内容是保存在webviewCache⽂件夹下。
webview中也是可以设置缓存是否可⽤的,⼀般是通过WebSettings对象设置,下⾯我们就来看⼀下WebSettings对象的使⽤。
Android中webview组件有⼏个重要的⽅法
WebSettings webSettings = Settings();
人工抽脂webSettings.setJavaScriptEnabled(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setAllowFileAccess(false);
webSettings.setUseWideViewPort(false);
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
webSettings.setDatabaseEnabled(false);
webSettings.setAppCacheEnabled(false);
webSettings.setBlockNetworkImage(true);
// 设置WebView的Client
mWebView.setWebViewClient(new MWebViewClient(this));
// 设置可现实js的alert弹窗
mWebView.setWebChromeClient(new WebChromeClient());
可以看到我们可以使⽤WebSettings对象设置缓存是否可⽤,缓存DB是否可⽤等。我们需要⾸先确保这⾥设置了缓存可⽤,才可以继续设
置使⽤何种缓存策略。
下⾯我们来看⼀下webview的五种缓存模式:
LOAD_CACHE_ONLY: 不使⽤⽹络,只读取本地缓存数据
LOAD_DEFAULT: 根据cache-control决定是否从⽹络上取数据。
防盗螺母LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作⽤同LOAD_DEFAULT模式
LOAD_NO_CACHE: 不使⽤缓存,只从⽹络获取数据.
LOAD_CACHE_ELSE_NETWORK,只要本地有,⽆论是否过期,或者no-cache,都使⽤缓存中的数据。
⼏种缓存⽅式的实现
(1)使⽤LOAD_CACHE_ELSE_NETWORK缓存模式,这样需要在APP退出的时候清除webview缓存,但是这样做有⼀个弊端就是如果
当前App已经是打开状态,⽹页内容有更新的话不会看到;
(2)使⽤LOAD_DEFAULT这种缓存⽅式,数据从缓存中获取还是从⽹络中获取根据H5页⾯的参数判断,这样做的好处是可以动态的处
理更新内容;
设置缓存
//开启 database storage API 功能
String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME;
//      String cacheDirPath = getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME;
Log.i(TAG, "cacheDirPath="+cacheDirPath);
//设置数据库缓存路径
//设置  Application Caches 缓存⽬录
//开启 Application Caches 功能
退出App时清除缓存
//清理Webview缓存数据库
try {
deleteDatabase("webview.db");
deleteDatabase("webviewCache.db");
} catch (Exception e) {
e.printStackTrace();
}
//WebView 缓存⽂件
File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME);
Log.e(TAG, "appCacheDir path="+AbsolutePath());
File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+"/webviewCache");
Log.e(TAG, "webviewCacheDir path="+AbsolutePath());
//删除webview 缓存⽬录
ists()){
deleteFile(webviewCacheDir);
}
/
/删除webview 缓存缓存⽬录
ists()){
deleteFile(appCacheDir);
}
其他的缓存策略
⽹页在加载的时候暂时不加载图⽚,当所有的HTML标签加载完成时在加载图⽚具体的做法如下初始化webview的时候设置不加载图⽚webSettings.setBlockNetworkImage(true);
然后在html标签加载完成之后在加载图⽚内容:
@Override
public void onPageFinished(WebView view, String url) {
}
O(∩_∩)O哈哈~,这样做的好处就是可以给⼈的感觉⽹页加载速度很快…
将⽹页内容中需要的js,css引⽤⽂件保存在App本地
加载⽹页内容时,在加载完成html后替换页⾯内容引⽤的地址改为本地的资源⽂件地址,这样可以直接加载本地的资源⽂件加快资源的访问速度,⽬前主流的新闻客户端访问webview时多采⽤这种⽅式。
好吧,讲解完了webview的性能优化问题之后我们在讲解⼀下如何在H5页⾯种⼊Cookie信息。
H5页⾯种⼊Cookie问题
app中存在webview控件,既可以通过Native与js代码交互的⽅式实现信息的交互也可以通过cookie的⽅式与实现Native与H5端的交互,查询的好多资料各种各样的实现⽅式都有,最终不断尝试基本实现了需求,现说明⼀下最终的实现⽅式;
/**
* 客户端将cookie种⼊H5页⾯中,H5页⾯可以通过js代码实现对native种⼊cookie信息的读取操作
*/
public static void synCookies(Context context, String url, String cookie) {
CookieManager cookieManager = Instance();
cookieManager.setAcceptCookie(true);
Uri uri = null;
String domain = "";
try {
uri = Uri.parse(URLDecoder.decode(url, "utf-8"));
domain = Host();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String cookieStr = Cookie(url);
// 判断token是否发⽣变化,发⽣变化的话则更新cookie
L.i("cookieEquce:" + cookie.equals(H5Constant.TOKEN + "="));
if (!TextUtils.isEmpty(cookieStr) && ains(cookie) && !cookie.equals(H5Constant.TOKEN + "=")) {
return;
}
// 更新domain(不再从UserInfo中获取,更改为从UrlInfo中获取)
if (!TextUtils.UrlInfo().getB4Domain())) {
domain = UrlInfo().getB4Domain();
}
List<String> uaList = SystemUa(context);
String md = ";domain=" + domain;
// 添加经纬度信息到Cookie中
cookieManager.setCookie(url, "lat=" + Config.lat + md);
cookieManager.setCookie(url, "lng=" + Config.lng + md);
cookieManager.setCookie(url, cookie + ";" + md);
if (uaList != null && uaList.size() > 0) {
for (String coo : uaList) {
cookieManager.setCookie(url, coo + md);
}
}
}
其中CookieManager是cookie的管理对象,主要实现对⽹页cookie的注⼊与清除等⼯作。注⼊字符串的形式是:key=value;domain=url 的形式(其中url为需要注⼊cookie的url链接地址)
那么如何移除cookie呢?
/**
* 移除cookie
*/
public static void removeCookies(Context context) {
CookieManager cookieManager = Instance();
}
⼀般情况下都是在打开H5页⾯的时候种⼊Cookie信息,然后在离开H5页⾯的时候清除cookie信息。当然了通过cookie实现native与js的交互只是实现信息交互的⼀种⽅式,我们还可以通过js与java代码相互调⽤的⽅式实现相互交互,⽂章的后⾯会有介绍。
⽽下⾯我们再来讲解⼀下activity退出时webview报错的问题。
训练监控
Activity退出时webview报错的问题
前段时间在调试代码的时候,有⼀段关于webview的代码,即退出Fragment的时候清除webview,这时候在其他⼿机上是没有问题的,但是在三星Grand2中报错,⽽其报错信息是:
java.lang.Throwable: Error: WebView.destroy() called while still attached!
at Android.webkit.WebViewClassic.destroy(WebViewClassic.java:4173)
at Android.webkit.WebView.destroy(WebView.java:707)
UI.DestroyView(H5Fragment.java:202)
at Android.support.v4.app.Fragment.performDestroyView(Fragment.java:2167)
at Android.support.v4.veToState(FragmentManager.java:1141)
at Android.support.v4.veToState(FragmentManager.java:1248)
at Android.support.v4.veToState(FragmentManager.java:1230)
at Android.support.v4.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:2079)
at Android.support.v4.app.FragmentController.dispatchDestroy(FragmentController.java:235)
at Android.support.v4.Destroy(FragmentActivity.java:326)
at Android.support.v7.Destroy(AppCompatActivity.java:161)
UI.Destroy(BaseActivity.java:136)非接触式扭矩传感器
at Android.app.Activity.performDestroy(Activity.java:5543)
at Android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1134)
at Android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3637)
at Android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3672)
at Android.app.ActivityThread.access$1300(ActivityThread.java:168)
at Android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382)
at Android.os.Handler.dispatchMessage(Handler.java:99)
at Android.os.Looper.loop(Looper.java:176)
at Android.app.ActivityThread.main(ActivityThread.java:5493)
at flect.Method.invokeNative(Native Method)
at flect.Method.invoke(Method.java:525)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1225)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.java:1041)
at dalvik.system.NativeStart.main(Native Method)
程序也没有异常退出之类的动作,清除webview的代码是这样写的:防火罩
@Override
public void onDestroyView() {
mWebView.destroy();
}
这个错误⼤概的意思是:当你结束webview的时候,webview还依附在其⽗控件之下,应当在调⽤web
view.destory()⽅法之前接触他们之间的依附关系,那么既然错误提⽰信息已经很明显了,我们就根据错误信息尝试着⾸先执⾏webview⽗控件的清除⼯作,然后在执⾏webview控件的清除操作,所以代码中应该这样实现:
@Override
public void onDestroyView() {无机砂浆
mWebView.destroy();
}
这样经过修改之后特定机型上关于webview的错误就不在了。
webview中实现Native与js相互调⽤
上⾯我们介绍的通过cookie实现Android native与H5的信息交互只是⼀种⽅式,我们也可以通过java代码与js代码直接相互调⽤的⽅式实现Android native与H5信息的相互,这⾥简单的介绍⼀下使⽤⽅式
native代码调⽤H5的js代码

本文发布于:2024-09-24 14:27:06,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/4/277391.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:缓存   加载   实现   问题
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议