Android webview 关于返回键和历史栈的坑 Android webview 关于返回键和历史栈的坑

Android webview 关于返回键和历史栈的坑

最近在做一个webview加载出错时加载本地的出错页,刷新显示之前Url的内容。碰到了一连串的坑,同时也了解了webview。


            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                super.onReceivedError(view, errorCode, description, failingUrl);
                mFailUrl = failingUrl;
                view.getSettings().setJavaScriptEnabled(true);
                view.loadUrl(mErrorWebPage);
                view.addJavascriptInterface(new LinkInitialize(view), "LinkInitialize");

            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

上面代码是当加载出错的时候重写onreceivedError,在里面实现加载本地的错误页html。 
然后重点出现了,在点击back按键的时候,会出现之前的错误页。也就是说,webview的历史栈中存储了错误页的url。所以重写back事件。

@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            switch (keyCode) {
                case KeyEvent.KEYCODE_BACK:
                    WebBackForwardList history = mGachaWebView.copyBackForwardList();
                    int index = -1;
                    String url = null;
                    String currentUrl = mGachaWebView.getUrl();
                    while (mGachaWebView.canGoBackOrForward(index)) {
                        int currentIndex = history.getCurrentIndex();
                        String lastUrl = history.getItemAtIndex(currentIndex + index).getUrl();
                        if (!lastUrl.equals(mGachaWebView.getmErrorWebPage()) && !currentUrl.equals(lastUrl)) {
                            mGachaWebView.goBackOrForward(index);
                            url = lastUrl;
                            break;
                        }
                        index--;

                    }
                    if (url == null) {
                        onBackPressed();
                    }
                    if (history.getSize() == 2 && currentUrl.equals(mGachaWebView.getmErrorWebPage())) {
                        onBackPressed();
                    }
                    return true;
            }

        }
        return super.onKeyDown(keyCode, event);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

做完这里的时候,测试大部分页面,以为已经解决了问题,但是发现,当加载的url存在重定向问题的时候,就导致,始终退不回去了。比如说A->B->Error->B’ 
解释一下,A页面点击跳转到B页面,但是因为出错,所以直接跳转到自定义的Error出错页,出错页上有个刷新按钮,是js调用java代码,贴一个

@JavascriptInterface
        public void reloadUrl() {
            if(!isDoubleClick()){
                mHandler.post(new Runnable() {
                    public void run() {
                        webView.loadUrl(mFailUrl);
                    }
                });
            }

        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

刷新按钮点击后会重新webView.loadUrl(mFailUrl)之前失败的那个url,这时,因为B是一个重定向的Url,所以webview直接重定向到B’,webview的历史栈中是这样的A->B->Error->B’ 
并不是猜想的A->B->Error->B->B’。所以当点击回退按钮的时候,回到页面B,重定向到B’,循环往复,始终退不出去了。 
在单步调试的过程中发现,webview中的历史栈的来源,有两种,一种是调用loadUrl(),会把Url加入到历史栈中,一种是页面内点击跳转,会将点击的那个url加入到历史栈中。但是有特殊情况,如果load的页面存在重定向,那么重定向之前的那个url不会加入到历史栈中,只会把重定向后的url加入到栈中。

由于重定向导致的无法回退现象,可以在public boolean shouldOverrideUrlLoading(WebView view, String url)解决,

@Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {

                //do what you want 
               return false;
            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

完成。坑了两天看这玩意,想过很多方法,比如自己维护一个栈,但是想到重定向的情况,就觉得好不靠谱。

猜你喜欢

转载自blog.csdn.net/jhope/article/details/80728377
今日推荐