当前位置:  开发笔记 > 编程语言 > 正文

如何监听WebView完成加载URL?

如何解决《如何监听WebView完成加载URL?》经验,为你挑选了9个好方法。

我有一个WebView从Internet上加载页面.我想显示一个ProgressBar直到加载完成.

我如何监听完成页面加载WebView



1> ian..:

扩展WebViewClient并调用onPageFinished(),如下所示:

mWebView.setWebViewClient(new WebViewClient() {

   public void onPageFinished(WebView view, String url) {
        // do your stuff here
    }
});


这根本不是解决方案.调用此方法时,无法保证页面已加载.
此方法不保证加载完成,并且如果url加载需要一些中间URL导航,则可以多次调用.所以这个被多次调用.然而它是一种检查它的方法.
Google的设计太糟糕了。几乎所有时间,当此操作完成时,您都想针对父活动而不是Web视图本身进行操作。覆盖函数而不是订阅事件是一种常见的反模式,也是我不喜欢android开发的原因。

2> neteinstein..:

@ian这不是100%准确.如果页面中有多个iframe,则会有多个onPageFinished(和onPageStarted).如果你有几个重定向,它也可能会失败.这种方法解决了(几乎)所有问题:

boolean loadingFinished = true;
boolean redirect = false;

mWebView.setWebViewClient(new WebViewClient() {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
        if (!loadingFinished) {
            redirect = true;
        }

        loadingFinished = false;
        webView.loadUrl(urlNewString);
        return true;
    }

    @Override
    public void onPageStarted(WebView view, String url) {
        loadingFinished = false;
        //SHOW LOADING IF IT ISNT ALREADY VISIBLE  
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        if (!redirect) {
           loadingFinished = true;
            //HIDE LOADING IT HAS FINISHED
        } else {
            redirect = false; 
        }
    }
});

更新:

根据文档:当嵌入框架的内容发生变化时,不会调用onPageStarted,即单击目标为iframe的链接.

我在Twitter上发现了一个特定的案例,其中只有一个pageFinished被调用并且稍微搞乱了逻辑.为了解决这个问题,我添加了一个计划任务,在X秒后删除加载.在所有其他情况下都不需要这样做.

更新2:

现在使用当前的Android WebView实现:

boolean loadingFinished = true;
boolean redirect = false;

    mWebView.setWebViewClient(new WebViewClient() {

        @Override
        public boolean shouldOverrideUrlLoading(
                WebView view, WebResourceRequest request) {
            if (!loadingFinished) {
               redirect = true;
            }

            loadingFinished = false;
            webView.loadUrl(request.getUrl().toString());
            return true;
        }

        @Override
        public void onPageStarted(
                WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            loadingFinished = false;
            //SHOW LOADING IF IT ISNT ALREADY VISIBLE  
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if (!redirect) {
               loadingFinished = true;
                //HIDE LOADING IT HAS FINISHED
            } else {
                redirect = false; 
            }
        }
    });


您可能已经注意到onPageStarted的doc中的警告:当嵌入帧的内容发生更改时,on_Started将不会被调用,即单击目标为iframe的链接.因此,这可能会扭曲这些情况下的逻辑.BTW,@ polen的简化真的有用吗?
只是一个小小的修正.它实际上是"public void onPageStarted(WebView视图,String url,Bitmap favicon)"而不是"public void onPageStarted(WebView view,String url)"

3> SciSpear..:

我非常偏爱@NeTeInStEiN(和@polen)解决方案但是会用计数器实现它而不是多个布尔或状态监视器(只是另一种味道,但我认为可能会分享).它确实有一个关于它的JS细微差别,但我觉得逻辑更容易理解.

private void setupWebViewClient() {
    webView.setWebViewClient(new WebViewClient() {
        private int running = 0; // Could be public if you want a timer to check.

        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String urlNewString) {
            running++;
            webView.loadUrl(urlNewString);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            running = Math.max(running, 1); // First request move it to 1.
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if(--running == 0) { // just "running--;" if you add a timer.
                // TODO: finished... if you want to fire a method.
            }
        }
    });
}


你的代码看起来不错.我一直在尝试从我的webview加载html数据而不是url.但是如果第一个webview快速加载并且第二个webview开始加载之前,则会触发onPageFinished.正常情况.running = 1,running = 2, - running = 1, - running = 0.失败的异常情况 - running = 1, - running = 0,running = 1 running = 0

4> polen..:

我简化了NeTeInStEiN的代码是这样的:

mWebView.setWebViewClient(new WebViewClient() {
        private int       webViewPreviousState;
        private final int PAGE_STARTED    = 0x1;
        private final int PAGE_REDIRECTED = 0x2;

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
            webViewPreviousState = PAGE_REDIRECTED;
            mWebView.loadUrl(urlNewString);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            webViewPreviousState = PAGE_STARTED;
            if (dialog == null || !dialog.isShowing())
                dialog = ProgressDialog.show(WebViewActivity.this, "", getString(R.string.loadingMessege), true, true,
                        new OnCancelListener() {

                            @Override
                            public void onCancel(DialogInterface dialog) {
                                // do something
                            }
                        });
        }

        @Override
        public void onPageFinished(WebView view, String url) {

            if (webViewPreviousState == PAGE_STARTED) {
                dialog.dismiss();
                dialog = null;
            }

        }
 });

很容易理解,OnPageFinished如果前一个回调是在onPageStarted上,那么页面是完全加载的.


@polen PAGE_STARTED永远不会被清除?如果shouldOverrideUrlLoading()永远不会被调用怎么办?

5> Francesco La..:

如果您想要显示进度条,则需要监听进度更改事件,而不仅仅是完成页面:

mWebView.setWebChromeClient(new WebChromeClient(){

            @Override
            public void onProgressChanged(WebView view, int newProgress) {

                //change your progress bar
            }


        });

顺便说一下,如果你想只显示一个Indeterminate ProgressBar,那么覆盖onPageFinished方法就足够了



6> Skynet..:

我找到了一个优雅的解决方案,但没有经过严格的测试:

public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (m_webView.getProgress() == 100) {
                progressBar.setVisibility(View.GONE);
                m_webView.setVisibility(View.VISIBLE);
            }
        } 


我已经对其进行了测试,并且可以正常工作。当然,您可以从onPageFinished方法外部调用它,并使用Handler在短时间内进行检查-在某些情况下,您不想扩展WebViewClient类。

7> Robby Pond..:

使用setWebViewClient()并覆盖onPageFinished()


请注意重复和不可靠的答案.

8> Praveen..:

您可以通过webview类中的getProgress方法跟踪Progress Staus .

初始化进度状态

private int mProgressStatus = 0;

然后像这样加载AsyncTask:

private class Task_News_ArticleView extends AsyncTask {
    private final ProgressDialog dialog = new ProgressDialog(
            your_class.this);

    // can use UI thread here
    protected void onPreExecute() {
        this.dialog.setMessage("Loading...");
        this.dialog.setCancelable(false);
        this.dialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            while (mProgressStatus < 100) {
                mProgressStatus = webview.getProgress();

            }
        } catch (Exception e) {

        }
        return null;

    }

    protected void onPostExecute(Void result) {
        if (this.dialog.isShowing()) {
            this.dialog.dismiss();
        }
    }
}



9> EscapeNetsca..:

谢谢你的回答.它帮助了我,但我必须根据我的需要改进它.我有几个页面和完成,所以我添加了一个计时器,检查是否启动了pagefinish新的pagestart.好的,不好的解释.看代码:)

myWebView.setWebViewClient(new WebViewClient() {
        boolean loadingFinished = true;
        boolean redirect = false;

        long last_page_start;
        long now;

        // Load the url
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (!loadingFinished) {
                redirect = true;
            }

            loadingFinished = false;
            view.loadUrl(url);
            return false;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            Log.i("p","pagestart");
            loadingFinished = false;
            last_page_start = System.nanoTime();
            show_splash();
        }

        // When finish loading page
        public void onPageFinished(WebView view, String url) {
            Log.i("p","pagefinish");
            if(!redirect){
                loadingFinished = true;
            }
            //call remove_splash in 500 miSec
            if(loadingFinished && !redirect){
                now = System.nanoTime();
                new android.os.Handler().postDelayed(
                        new Runnable() {
                            public void run() {
                                remove_splash();
                            }
                        },
                        500);
            } else{
                redirect = false;
            }
        }
        private void show_splash() {
            if(myWebView.getVisibility() == View.VISIBLE) {
                myWebView.setVisibility(View.GONE);
                myWebView_splash.setVisibility(View.VISIBLE);
            }
        }
        //if a new "page start" was fired dont remove splash screen
        private void remove_splash() {
            if (last_page_start < now) {
                myWebView.setVisibility(View.VISIBLE);
                myWebView_splash.setVisibility(View.GONE);
            }
        }

});

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有