安卓WebView WebChromeClient:onProgressChanged()中进度值不准确。

6

我需要在 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);
    }
});

3
您要加载的URL是什么?您是否可能看到重定向?看起来结果在0-100范围内总是单调的,但它们正在重新启动。您使用的Android版本是什么? - ksasq
@ksasq 你是对的,有许多重定向,因此进度被重置了。谢谢。 - tamsler
4个回答

5
从我的实验中,我发现在相同的进度值下(例如:google.com 进度=100 会调用两次),onProgressChanged 可以为相同的 url 调用多次。
我还发现,在加载另一个 url 时,onProgressChanged 会晚一些被调用。时间表示例:
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
此时,我应该提到,在我的实验中,我覆盖 shouldOverrideUrlLoading() 来查看重定向,即使我没有看到重定向,上述情况仍然会发生。那么为什么会发生这种情况呢?
根据这个答案(为什么WebChromeClient.onProgressChanged和jquery的$(document).ready()回调之间有明显的延迟?):因为页面在脚本触发之前加载,文档准备就绪会等待所有HTML元素被加载,除了图片和类似的东西,所以你的脚本直到一切都被加载后才会触发,此时你的onprogresschanged已经首先收到100%,因为它可能比你的JavaScript具有更高的优先级,毕竟设备要求检查是否应该允许JS或不允许,因此必须通过一些检查才能调用此方法。

所以,把它全部放在一起,这就是你需要做的:

  1. 不要相信 onProgressChanged()。
  2. 在 onPageStarted() 中检查当前正在尝试加载的 url 是否与 webView.getUrl() 匹配。这是你的起点。将一个布尔值 finishedLoading 设置为 false。
  3. 假设当 onPageFinished 被调用时,webView.getUrl() 与你尝试加载的 url 相匹配,则认为页面已经加载完成。如果没有重定向,那么将 finishedLoading 标志设置为 true。但是,对于重定向,您需要执行第三步。
  4. 覆盖 shouldOverrideurlLoading()。如果新的 url 与最初加载的 url 不匹配(webView.loadUrl(new redirect url)),则加载新的 url 并将 finishedLoading 设置为 false。

代码

    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;
   }

3
最佳解决方案是使用webview的进度,而不是progress(从方法onProgressChanged(WebView view, int progress)返回整数值)。
伪代码:
@Override
public void onProgressChanged(WebView view, int progress) {
       progressBar.setProgress(yourWebView.getProgress());
}

这个解决方案在所有情况下都能很好地工作!

2
如@ksasq在上面的评论中指出,初始URL引起了许多重定向,因此onProgressChanged()被调用了很多次。

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!!)
            }
        }
    }


} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接