当前位置:   article > 正文

RSS阅读器练习笔记————WebView中图片缓存_rss 缓存 图片

rss 缓存 图片

本文来自http://blog.csdn.net/chenshaoyang0011转载请申明出处!

    在前面一篇笔记http://blog.csdn.net/chenshaoyang0011/article/details/8634235中,描述了解决XML中携带CDATAHTML实体字符的解决办法,接下来要解决的问题就是缓存图片。

    在这篇文章中主要记录了对以下问题的解决方法:

    1、WebView中图片点击事件的响应

    2、WebView图片缓存,并替换WebView默认图片(即图片未加载前显示的样式)

    在新闻内容显示的时候,图片是必不可少的,在内容加载完毕之后,图片的缓存也是非常必要的,毕竟对于手机应用,流量是非常宝贵的资源。对于图片,WebView本身有一个缓存数据库进行缓存。但是我使用的是另外一个思路进行图片的缓存——阻止WebView加载图片而是在WebView将文本加载好了之后,通过本地方法下载图片保存到本地后再显示到WebView中。这样,在使用WebView进行显示的时候能够更加的灵活。

    在实现上述提到的功能之前,需要了解Android的WebView如何实现Java代码与JavaScript代码的相互调用,推荐两篇博文http://blog.csdn.net/wangtingshuai/article/details/8631835 (实现简单调用)和http://blog.csdn.net/wangtingshuai/article/details/8635787 (实现图片点击)本文就不再赘述了。接下来就详细的探讨下上述功能的实现方法。

    一、响应WebView中图片点击事件。

    对于此功能的实现,可以参照http://blog.csdn.net/wangtingshuai/article/details/8635787 这篇文章。其中主要涉及到JS与JAVA代码的互调,这里我就不重新造轮子了。

    二、缓存WebView中的图片,替换默认图片

    WebView本身有自己的缓存机制,但是由于没有找到相关的文档,感觉不是很好用,所以我就想了另外一个方法。主要思路是这样的:1、使用jsoup来解析html;2、获取所有图片的URL(即img标签的url),替换为需要显示默认状态的图片的URI,最后在图片下载好后将这些URI按照某种映射规则替换为本地的URI(即相当于将这个img指向了本地的一张图片);3、关闭WebView加载图片,加载html;4、在文本加载完毕之后,开始依次下载所有的img到本地,每张图片下载好后,调用js代码刷新图片。

    下面就一步一步的来实现。

    1、使用jsoup解析html

    这个我在http://blog.csdn.net/chenshaoyang0011/article/details/8640987 已经简单的介绍了,详细的使用还需参照http://jsoup.org/ (后文中代码使用了很多jsoup的api)。

    2、获取所有图片的url,并替换为本地图片(需要用来替换WebView默认显示效果的图片)。

    获取到的图片的url需要保存到一个属性List<String>中:

        

public List<String> imgUrls = new ArrayList<String>();

  使用以下代码片段可以从html中获取所有img标签的url,并且按照如下映射规则替换为本地图片的URI(当然这个映射规则由自己定啦~~):"http://.../xx.xx"替换为"file://mnt/sdcard/test/xx.xx"其实就是将图片下载后保存的路径。

                

  1. Document doc = null;
  2. imgUrls.clear();
  3. Elements es = doc.getElementsByTag("img");
  4. for (Element e : es) {
  5. String imgUrl = e.attr("src");
  6. imgUrls.add(imgUrl);
  7. String imgName;
  8. File file = new File(imgUrl);
  9. imgName = file.getName();
  10. if(imgName.endsWith(".gif")){
  11. e.remove();
  12. }else{
  13. String filePath = "file:///mnt/sdcard/test/" + imgName;
  14. e.attr("src","file:///android_asset/web_logo.png");
  15. e.attr("src_link", filePath);
  16. e.attr("ori_link",imgUrl);
  17. String str = "window." + Js2JavaInterfaceName + ".setImgSrc('"
  18. + filePath + "')";
  19. e.attr("onclick", str);
  20. }
  21. }

    3、关闭WebView加载网络图片,加载html先显示文本内容

    这样做主要是为了改善用户体验,阻止WebView自己加载图片是避免重复下载图片浪费流量。

    首先关闭WebView加载网络图片,其实由于我们已经替换掉了img中url,可以忽略这一步。但是为了避免有漏网之鱼,还是加上好些:

    webView.getSettings().setBlockNetworkImage(true);

    接下来加载html:

   

  1. //result为解析后获得的html文本
  2. webView.loadDataWithBaseURL(null, result, "text/html", "utf-8", null);

    4、在文本加载完毕之后,开始依次下载所有的img到本地,每张图片下载好后,调用js代码刷新图片。

    文本内容加载完毕之后,就可以开始加载图片内容了,在html内容加载完之后,会调用WebViewClient.onPageFinished(WebView view, String url)这个方法。我们就可以在这个方法中执行图片的下载保存工作。

    以下的代码片段就实现了开始下载的功能:

            

  1. webView.setWebViewClient(new WebViewClient(){
  2. public void onPageFinished(WebView view, String url){
  3. //DownloadWebImgTask是用于下载图片的类
  4. DownloadWebImgTask downloadTask = new DownloadWebImgTask();
  5. //获取所有图片的url
  6. List<String> urlStrs = parser.getImgUrls();
  7. String urlStrArray[] = new String[urlStrs.size() + 1];
  8. urlStrs.toArray(urlStrArray);
  9. //开始下载
  10. downloadTask.execute(urlStrArray);
  11. }
  12. });

    上面的代码中DownloadWebImgTask的实现如下,其功能就是批量的下载图片,并且在每张图片下载好后刷新WebView。由于WebView本身没有提供接口实现图片的单独刷新(至少我没有找到。。。),所以只能借助js来实现此功能。

    

  1. public class DownloadWebImgTask extends AsyncTask<String, String, Void>{
  2. public static final String TAG = "DownloadWebImgTask";
  3. @Override
  4. protected void onProgressUpdate(String... values) {
  5. super.onProgressUpdate(values);
  6. //加载下面的js代码实现单张图片的刷新
  7. webView.loadUrl("javascript:(function(){" +
  8. "var objs = document.getElementsByTagName(\"img\"); " +
  9. "for(var i=0;i<objs.length;i++) " +
  10. "{"
  11. + " var imgSrc = objs[i].getAttribute(\"src_link\"); "
  12. + " var imgOriSrc = objs[i].getAttribute(\"ori_link\"); "
  13. + " if(imgOriSrc == \"" + values[0] + "\"){ "
  14. + " objs[i].setAttribute(\"src\",imgSrc);}" +
  15. "}" +
  16. "})()");
  17. }
  18. @Override
  19. protected void onPostExecute(Void result) {
  20. //这段代码只是确保所有图片都顺利的显示出来
  21. webView.loadUrl("javascript:(function(){" +
  22. "var objs = document.getElementsByTagName(\"img\"); " +
  23. "for(var i=0;i<objs.length;i++) " +
  24. "{"
  25. + " var imgSrc = objs[i].getAttribute(\"src_link\"); " +
  26. " objs[i].setAttribute(\"src\",imgSrc);" +
  27. "}" +
  28. "})()");
  29. super.onPostExecute(result);
  30. }
  31. @Override
  32. protected Void doInBackground(String... params) {
  33. URL url = null;
  34. InputStream inputStream = null;
  35. OutputStream outputStream = null;
  36. HttpURLConnection urlCon = null;
  37. //若传入参数为空,则直接返回
  38. if(params.length == 0)
  39. return null;
  40. File dir = new File(Environment.getExternalStorageDirectory() + "/test/");
  41. if(!dir.exists()){
  42. dir.mkdir();
  43. }
  44. for(String urlStr : params){
  45. try {
  46. if(urlStr == null){
  47. break;
  48. }
  49. File tempFile = new File(urlStr);
  50. int index = urlStr.lastIndexOf("/");
  51. String fileName = urlStr.substring(index + 1, urlStr.length());
  52. File file = new File(Environment.getExternalStorageDirectory() + "/test/" + fileName);
  53. if(file.exists()){
  54. continue;
  55. }
  56. try {
  57. file.createNewFile();
  58. } catch (IOException e) {
  59. e.printStackTrace();
  60. }
  61. url = new URL(urlStr);
  62. urlCon = (HttpURLConnection)url.openConnection();
  63. urlCon.setRequestMethod("GET");
  64. urlCon.setDoInput(true);
  65. urlCon.connect();
  66. inputStream = urlCon.getInputStream();
  67. outputStream = new FileOutputStream(file);
  68. byte buffer[]=new byte[1024];
  69. int bufferLength = 0;
  70. while((bufferLength = inputStream.read(buffer)) > 0){
  71. outputStream.write(buffer, 0, bufferLength);
  72. }
  73. outputStream.flush();
  74. publishProgress(urlStr);
  75. } catch (MalformedURLException e) {
  76. // TODO Auto-generated catch block
  77. e.printStackTrace();
  78. } catch (IOException e) {
  79. // TODO Auto-generated catch block
  80. e.printStackTrace();
  81. }finally{
  82. try {
  83. if(inputStream != null){
  84. inputStream.close();
  85. }
  86. } catch (IOException e1) {
  87. // TODO Auto-generated catch block
  88. e1.printStackTrace();
  89. }
  90. try {
  91. if(outputStream != null){
  92. outputStream.close();
  93. }
  94. } catch (IOException e) {
  95. // TODO Auto-generated catch block
  96. e.printStackTrace();
  97. }
  98. }
  99. }
  100. return null;
  101. }
  102. }

    这样图片就被正常的显示出来,并且在本地已经有缓存了。

    最后照例给出一个简单的demo:http://download.csdn.net/detail/chenshaoyang0011/5130931

    

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/286428
推荐阅读
  

闽ICP备14008679号