本次工作我自己想挑战论坛页的展示部分,因为自己想了解下如何用webview来开发应用。
一、要将一个网页加载到本地展示,就需要本地建立webview的一个模板文件然后解析后台传输过来的html代码,本地模板文件一般置于assets下,其中模板文件包括html模板,html模板中包括的css,js以及image等。为什么选择assets文件夹来存放这些资源,我想是因为在res下面的一些资源文件夹无法以目录结构来显示,而且模板文件根本无须映射到R文件中。
然后需要一个工具类来对后台传送过来的html进行解析,然后拼凑成自己想要的html然后利用webview的loadDataWithBaseURL方法加载即可。
二、因为业务需求需要对webview中得图片点击显示相册大图,所以本次工作我直接用Universal-Image一个第三方图片加载库替代了webview的加载图片过程。为什么使用第三方来管理webview的图片基于以下几个方面考虑:
1、当图片很多时,进入webview页面会等待图片加载完成比较耗时。当然可以通过其他手段来解决这个办法,比如在webviewclient里面的onLoadResource里面对加载资源进行判断,提前结束加载过程;或者进入webview时直接设置getSettings().setBlockNetWorkImage(true),在加载完成后再直接设置为false。
2、不希望同样的一张图片被下载两次,在点击图片放大显示希望复用本地下载下来的缓存。当然webview是有自己一套缓存机制的,包括DomStorage,AppCache还有数据库,默认情况下使用的DomStorage,貌似是将缓存直接放在内存中,我跟踪下源码,貌似最后是交给第三方去实现的,因此对这个缓存不甚了解。而AppCache和volley用得缓存有点类似,用在本地生成一个journal目录文件,然后一一对应生成缓存文件。这个缓存目录大小和路径是可以设置的。我没有了解过对应文件名的命名规则,因为即使可以复用webview缓存的文件,对于业务需求还是不够的。因为当webview在一张图片还未加载完成的,我点击这张图片,这张图片放大展示时会不存在,除非我能直接调用webview加载图片的机制,感觉讳莫如深。当然,当我发现图片不存在时,我也可以重新利用第三方图片来加载,但是这样的话还是下载了两次图片。
3、点击查看大图的时候当图片没有加载完成时,希望看到一个进度条表明图片加载的加载进度,所以即使直接用webview加载图片机制,除非做深度研究定制,否则实现不了以上需求。所以直接采用Universal-Image来管理webview的大图。
采用第三方图片加载库来管理webview的图片要做到以下步骤,在解析html的时候将图片链接首先替换成本地默认图片(即替换<img src="*"),拿到该图片链接,使用Universal-Image下载图片,下载完成后存在缓存里,然后拿到缓存路径赋给该图片标签的src。点击图片时,进入图片相册,当图片下载完成时,Universal-Image会直接拿到缓存图片加载出来,如果没有加载完成,直接将加载过程交给Universal-Image去做,他有自己的管理线程池,其中一个加载完成后,另一个会直接读取缓存。
三、webview嵌入在activity中,一般会配置下webview得setting,大概如下:
webViewSetting.setJavaScriptEnabled(true);webViewSetting.setAllowFileAccess(true);webViewSetting.setDefaultTextEncodingName("UTF-8");
mWebView.setWebViewClient(new MyWebViewClient());mWebView.setWebChromeClient(new WebChromeClient());mWebView.addJavascriptInterface(new WebAppInterface(this), obj); 前三句大概意思就是允许js,允许webview获取文件,设置webview编码为utf-8.后三句就是设置设置webview的webviewclient,webchromeclient以及js和本地安卓的连接接口。在本项目中没有利用到webchromeclie的地方,因此没有对其进行多少研究。
webviewclient里面包含着onReceivedError,onPageStarted,onPageFinished,shouldOverrideUrlLoading等一系列方法,前三个方法可以自定义失败时,加载开始时,加载结束时的行为,最后一个方法可以自定义webview里面链接的点击事件。
四、总结项目遇见的几个坑或经验:
1、即使Universal-Image称自己管理线程池,但我在管理webview的过程中发现直接调用会发现他的加载会卡UI线程,通过输出线程id发现,其加载图片的线程总有一个和webview所在的activity的线程id一样,因此在图片众多时,加载过程会相当之卡。后面对每个加载过程,重新开创一个线程来执行该操作,但在这里输出线程id发现加载图片的线程id和开创出来的线程id没有一个一致,不懂这是为什么,我会在后面去研究volley,Universal-image以及eventbus三个开源框架,但至少在现在解决了加载图片时卡ui线程的问题。
2、当webview需要滑动时,利用jquery可以实现效果更好更平滑的滑动,
function jumpToLou(pid){ $("html,body").stop(true); $("html,body").animate({scrollTop: $("#pid_"+pid).offset().top}, ‘normal‘);
3、html模板指定这行
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
表情html自适应手机屏幕,我不知道为什么html的1px对应到机器上却是2px,但在项目中我都是做这样的换算。当后台传送的html写死了样式,超过了360px,即手机屏的720px,那么我只能写jquery捕获指定元素的style,然后将超过360px的标签的宽度缩小一半。
4、shouldOverrideUrlLoading在有的机器上得webview中会对非英文字符进行IDN操作,导致直接读取url会不正确。我因为不想了解IDN具体算法,在解析html的时候我会对相关的链接自己调用api中的IDN.toASCII,然后在shouldoverrideUrlLoading使用IDN.toUnicode变换回来。
5、使用css对webview的image设置圆角时,不能只对包含image的span标签设置圆角,必须对image标签也施加圆角,否则有的机器的webview并不支持,比如红米手机和三星的大多数低端机并不支持。
.img{position: absolute; left: -40px; top:-5px; display:block; width: 30px;height: 30px; -webkit-border-radius: 25px; -o-border-radius: 25px;-ms-border-radius: 25px; border-radius: 25px; overflow: hidden;background-clip:padding-box;}
T_T,当时还有好多经验都已经忘记了,看来还是要及时总结才行,不然都相当于没有沉淀了。从现在做起~