Webview 圖片異步加載及bug解決

在項目中新聞顯示需要使用圖片的異步加載,並且在加載圖片前和加載圖片失敗時顯示默認圖片。

關於webview中圖片的異步加載的思路如下:

方案一:由前端同學全權負責(使用js實現異步加載)

方案二:android端進行處理

(1)  從相應請求獲取到頁面的數據,處理其中的img標籤,將img標籤中的src屬性存儲在img標籤中的ori_link屬性中,給img標籤中的src屬性賦值你默認圖片所在路徑,給img標籤中的src_link屬性賦值你的圖片下載後保存的路徑

 

 private voidhandleImageClickEvent(Document doc) {
     Elements container =doc.getElementsByTag("article");
     for (Element ce : container) {
        Elements es = ce.getElementsByTag("img");
        for (Element e : es) {
           String imgUrl = e.attr("src");
           if(!imgUrl.startsWith("http://")){
               imgUrl = Constants.PIC_URL+imgUrl;
           }
           imgUrls.add(imgUrl);
           String imgName;
           imgName = StrMD5.getStrMD5(imgUrl);;
           String filePath = "file:///mnt/sdcard/"
                  + Constants.WEB_IMAGE_CACHDIR + "/" +imgName;
           e.attr("src", "file:///android_asset/news_info_default_image.jpg");
           e.attr("src_link", filePath);
           e.attr("ori_link", imgUrl);
        }
    }

(2)  使用webview的loadDataWithBaseURL(Constants.BASE_URL, result,"text/html", "utf-8", null);

Constants.BASE_URL 是爲了使在一些頁面中使用js或其他方式訪問自己工程相對路徑資源的時候使用的。

(3)  重寫webview的WebViewClient ,在onPageFinished方法中啓動圖片異步加載方法:

在task的doInBackground中下載圖片並保存到sd卡指定位置,下載完一個就通知publishProgress(urlStr) urlStr是圖片網址。

在task的onProgressUpdate方法中加載替換img屬性的js:

@Override
  protected void onProgressUpdate(String...values) {
     super.onProgressUpdate(values);
 
     mNewsInfoWebview
           .loadUrl("javascript:(function(){"
                  +"var contener =document.getElementsByTagName(\"article\");"
                  +"var objs;"
                  +"for(var i=0;i<contener.length;i++){ varobjs=contener[i].getElementsByTagName(\"img\")}"
                  + "for(var i=0;i<objs.length;i++)  "
                  + "{"
                  + "    var imgSrc =objs[i].getAttribute(\"src_link\"); "
                  + "    var imgOriSrc =objs[i].getAttribute(\"ori_link\"); "
                  + " if(imgOriSrc == \"" + values[0] + "\"){"
                  + "   objs[i].setAttribute(\"src\",imgSrc);}"
                  + "}" + "})()");
}
 


 

Values是publishProgress傳入的url

 

     但是這種方式有個問題:當用戶sd卡不存在或者用戶存儲設備非標準時,圖片無法顯示。

爲了解決這個問題,有一下兩個方案:

(一)  使用多級緩存:mem+?+sd ?可以使數據庫,可以使非sd卡之外存儲位置(暫時未進行了解)

(二)  直接使用webview自帶緩存:

(1)  修改webview緩存模式:webview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);

(2)  在獲取服務器端html時對img進行以下處理:

e.attr("src", "file:///android_asset/news_info_default_image.png");
e.attr("onerror","this.src='file:///android_asset/news_info_default_image.png'");
        e.attr("ori_link", imgUrl);


onerror方法是當圖片加載不出來時,瀏覽器默認顯示圖片

啓動後臺異步加載圖片方法不再寫文件,而是直接調用js方法進行url替換:

  

@Override
  protected voidonProgressUpdate(String... values) {
     super.onProgressUpdate(values);
     mNewsInfoWebview
     .loadUrl("javascript:(function(){"
           + "var objs = document.getElementsByTagName(\"img\");"
           + "for(var i=0;i<objs.length;i++)  "
           + "{"
           + "    var imgOriSrc =objs[i].getAttribute(\"ori_link\"); "
           + " if(imgOriSrc == \"" + values[0] + "\"){"
           + "    objs[i].setAttribute(\"src\",imgOriSrc);}"
           + "}" + "})()");
  }

 

 

總結:由於每次加載頁面都是通過loadDataWithBaseURL方法,所以即使服務器端頁面有進行修改,也不會由於瀏覽器緩存造成不能更新的問題。但是更新頻繁就會造成緩存文件過多,因此需要增加機制清理緩存。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章