Android WebView WebChromeClient:onProgressChanged()中的进度值不准确

时间:2014-03-06 00:15:01

标签: android webview webchromeclient

我需要在WebView中访问进度值 - > WebChromeClient - > onProgressChanged()。进度整数值不会从0增加到100,而是跳转。以下是加载一页的示例日志输出和相关的进度号:

DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 30
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 30
DEBUG:  progress : 100
DEBUG:  progress : 10
DEBUG:  progress : 30
DEBUG:  progress : 37
DEBUG:  progress : 45
DEBUG:  progress : 48
DEBUG:  progress : 49
DEBUG:  progress : 50
DEBUG:  progress : 52
DEBUG:  progress : 54
DEBUG:  progress : 56
DEBUG:  progress : 59
DEBUG:  progress : 61
DEBUG:  progress : 63
DEBUG:  progress : 66
DEBUG:  progress : 68
DEBUG:  progress : 70
DEBUG:  progress : 73
DEBUG:  progress : 75
DEBUG:  progress : 77
DEBUG:  progress : 79
DEBUG:  progress : 82
DEBUG:  progress : 84
DEBUG:  progress : 86
DEBUG:  progress : 87
DEBUG:  progress : 88
DEBUG:  progress : 89
DEBUG:  progress : 100

我做错了什么?

代码:

webView.setWebChromeClient(new WebChromeClient() {
    public void onProgressChanged(WebView view, int progress) {
        Log.i(LOG_TAG, "DEBUG: progress : " + progress);
    }
});

4 个答案:

答案 0 :(得分:5)

根据我自己的实验,我发现onProgressChanged可以针对相同的进度值多次调用相同的网址(例如:google.com进度= 100次调用两次)。

我还发现当你加载另一个url时,onProgressChanged将被调用为一个url。时间表示例:

  1. 加载google.com
  2. ProgressChanged = 100,webView.geturl():google.com
  3. 加载amazon.com
  4. ProgressChanged = 40,webView.getUrl():amazon.com
  5. ProgressChanged = 100,webView.getUrl():google.com
  6. 此时,我应该提一下,在我的实验中,我重写了shouldOverrideUrlLoading()来查看重定向,即使我没有看到重定向,上面仍然会发生。那么为什么会这样呢?

    根据这个答案(Why is there a noticeable delay between WebChromeClient.onProgressChanged and jquery's $(document).ready() callbacks?):因为在触发脚本之前加载了一个页面,所以文档就绪会查找除了图像和类似内容之外首先加载的所有html元素,因此你的脚本不会触发直到所有内容都被加载,到那时你的onprogresschanged首先收到100%,因为它可能比你的javascript具有更高的优先级,因为所有设备都要求检查是否应该允许js所以它必须先经过一些检查这个方法叫做。

    所以要把它们放在一起这就是你需要做的事情:

    1. 不要信任onProgressChanged()。
    2. onPageStarted()检查您尝试加载的当前URL是否与webView.getUrl()匹配。这是你的出发点。将boolean finishedLoading设置为false。
    3. 假设在调用onPageFinished时加载了您的页面,并且webView.getUrl()与您尝试加载的URL匹配。如果没有重定向,则将finishedLoading标志设置为true。但是,对于重定向,您需要按照步骤3进行操作。
    4. 覆盖shouldOverrideurlLoading()。如果新网址与最初加载的网址不匹配,请加载新网址(webView.loadUrl(new redirect url))并将finishedLoading设置为false。
    5. 代码

          private boolean isCurrentUrl(String url){
              return url.toLowerCase().contains(currentUrl.toLowerCase());
          }
      
         public void onPageStarted(WebView webView, String url,     
             android.graphics.Bitmap bitmap){
      
                      if (isCurrentUrl(url)){
                          pageLoaded = false;
                      }
         }
      
         public void onPageFinished(WebView webview, String url){
             if (isCurrentUrl(url)){
                 pageLoaded = true;
             }
         }
      
         public boolean shouldOverrideUrlLoading(WebView view, String 
             url){
             if (!currentUrl.equalsIgnoreCase(url)){
                 currentUrl = url;
                 view.loadUrl(currentUrl);
                 return true;
             }
             return false;
         }
      

答案 1 :(得分:2)

正如@ksasq在上面的评论中指出的那样,初始URL导致了许多重定向,因此多次调用onProgressChanged()。

答案 2 :(得分:1)

最佳解决方案是使用webview的进度而不是进度(方法onProgressChanged(WebView视图,int进度)中的整数值)

伪代码,

@Override
public void onProgressChanged(WebView view, int progress) {
       progressBar.setProgress(yourWebView.getProgress());
}

此解决方案适用于所有情况!

答案 3 :(得分:0)

webView有两个进度。 webView.getProgress()可提供更准确的进度,包括媒体文件的进度。 onProgressChanged()进度根据页面的可见性给出相对进度。下面的代码对我来说很好。在这里,我正在使用自定义的webView。

import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.webkit.WebChromeClient
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import com.xyz.interfaces.WebViewLoadingProgressListener


class MyWebView : WebView {

    private var webViewLoadingProgressListener: WebViewLoadingProgressListener? = null

    /**
     * to avoid webView progress inconsistency
     * and to get progress in incremental order
     */
    private var loadProgressCounter: Int? = null

    constructor(context: Context) : super(context) {
        initView(context)
    }

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        initView(context)
    }

    fun setWebViewLoadingProgressListener(webViewLoadingProgressListener: WebViewLoadingProgressListener) {
        this.webViewLoadingProgressListener = webViewLoadingProgressListener
    }

    var totalContentHeight = 0

    private fun initView(context: Context) {
        this.settings.javaScriptEnabled = true
        this.settings.domStorageEnabled = true
        this.settings.setAppCacheEnabled(true)
        this.settings.loadsImagesAutomatically = true
        this.settings.loadWithOverviewMode = true
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            this.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
        }


        this.webViewClient = object : WebViewClient() {
            /**
             * to restrict use of external browsing
             */
            override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
                view?.loadUrl(url)
                /**
                 * resetting on page change
                 */
                loadProgressCounter = null
                return true
            }
        }

        this.webChromeClient = object : WebChromeClient() {
            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                /**
                 * use webView.getProgress() for more precise progress
                 */

                /**
                 * allowing incremental progress only
                 */
                if (loadProgressCounter == null || loadProgressCounter!! <= newProgress) {
                    loadProgressCounter = newProgress
                }
                /**
                 * sends progress to required class
                 */
                webViewLoadingProgressListener?.onProgressChange(loadProgressCounter!!)
            }
        }
    }


}