1. 程式人生 > >Android WebView 因重定向無法正常goBack()解決方案

Android WebView 因重定向無法正常goBack()解決方案

 首先說下問題,初始頁面為A,點選某個連結跳轉到B(http://xxx.com.cn/),B頁面重定向到C頁面(http://xxx.com.cn/website/index.html)

當呼叫webview.goBack()時,頁面回退到B,然後接著會重定向回C頁面.

這樣會導致兩個問題:

1. 無法回退到webview的初始頁面A

2. 無法正常退出Activity或者Fragment(只有還未載入完C時進行回退才能退出頁面)

關於如何解決這個問題,我總結了如下三種方法,可以根據具體情況進行使用:

一. 首先需要和前端開發人員溝通,看重定向是否必要,如果跳轉連結只是域名,然後預設重定向到  域名/index.html,並沒有特殊處理的話,那麼這種重定向並沒有意義.

只要將網頁中的連線,比如

<a href="http://xxx.com.cn"/>

直接替換為 <a href="http:///xxx.com.cn/index.html"/>

即可解決該問題.

二.頁面中的重定向是必須的,那麼我們就需要自己維護一個webview的歷史棧,根據自己的需求進行過濾跳轉或者重新載入頁面:

判斷到當前為重定向後的連結,那麼那麼當回退的時候就需要忽略上一級的連結,不使用webview.goback(),移除重定向和重定向後的url,

獲取到初始頁面連結後自己進行loadUrl()操作.

3.還有一種方法,和方法2類似,需要自己維護webview的歷史棧,但是需要前端的配合,提供js函式獲取網頁是否進行重定向

在webviewClient回撥shouldoverloading()中過濾url時,若屬於重定向的地址,則不加入棧中,回退時根據歷史棧載入即可.

這裡主要講一下方法二:

首先定義一個歷史棧 :

private ArrayList<String> loadHistoryUrls = new ArrayList<String>();

把初始頁面Url加入 loadHistoryUrls.add(INITAL_WEB_URL);

然後加入載入的url:  public boolean shouldOverrideUrlLoading(WebView view,String url){            //將過濾到的url加入歷史棧中            loadHistoryUrls.add(url);            return true;                     }

最後在webview.goback()處理:

@Override     public boolean onKeyDown(int keyCode, KeyEvent event) {         //判斷是否可以返回操作         if (webView.canGoBack() && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {            //過濾是否為重定向後的連結              if(loadHistoryUrls.size()>0&&loadUrls.get(loadHistoryUrls.size()-1).contains("index.html"))                //移除載入棧中的最後兩個連結              loadHistoryUrls.remove(loadHistoryUrls.get(loadHistoryUrls.size()-1));                loadHistoryUrls.remove(loadHistoryUrls.get(loadHistoryUrls.size()-1));                //載入重定向之前的頁              webview.load(loadUrls.get(loadHistoryUrls.size()-1));               return true;             }                     }           }

關於載入棧,後來發現webview本身也有對應的API:

           //獲取歷史列表             WebBackForwardList mWebBackForwardList = webView.copyBackForwardList();

不過這個api可能受系統版本的影響或者不同手機系統進行了修改 所以解決該問題時,大家可以自己根據需求,自己維護載入的歷史棧或者直接呼叫系統api.

這裡總結一下,若重定向非必要,採取方案一,最簡單,修改量也非常小. 重定向必要,則使用方案二或者方案三.

因為需要和前端人員互動,方案三所需要的溝通,開發,維護的成本要比方案二高出不少,但對於是否重定向的判斷非常準確,若有多個重定向的情況,一次開發完成後不需要對程式碼再次改動.  方案二則需要寫死需要過濾的url,若出現多個重定向,則會顯得程式碼比較臃腫,每次都需要重新增加程式碼. 具體使用依據專案中的開發情況而定.

       最後再補充一種通用的辦法,但是需要後臺的強大支援: 在webview進行載入時,將請求傳送至伺服器,然後由伺服器進行分析處理,將處理後的結果返回給客戶端進行顯示. 並且可以由伺服器對網頁內容進行編碼或者取出冗餘,並結合cdn提升響應速度,這也是目前瀏覽器開發常用的一種策略.但是需要大量的資料收集,分析和處理,對於伺服器的依賴比較嚴重,若開發進度較緊或者公司資源有限,可先參照以上辦法進行解決.

     最重還要講的一點, 本篇文章主要是對於載入己方開發的H5中遇到問題的解決,至於第三方網站載入,這個是沒有辦法解決的. 包括微信上也一樣,對於各種公眾平臺和第三方連結,是沒有通用解決方案的, 所以他們在互動上進行了處理 ,在H5進行一次跳轉就會在標題欄左上角出現關閉按鈕. 畢竟使用者是不知道快速連續點選兩次返回才能正常返回首頁的.