如何监听 WebView 完成加载 URL?

Posted

技术标签:

【中文标题】如何监听 WebView 完成加载 URL?【英文标题】:How to listen for a WebView finishing loading a URL? 【发布时间】:2011-03-10 02:50:09 【问题描述】:

我有一个WebView,它正在从 Internet 加载一个页面。我想显示ProgressBar,直到加载完成。

如何监听WebView的页面加载完成?

【问题讨论】:

请考虑将我的答案标记为正确,因为它解决了一些 ian 没有解决的问题。 我认为在页面加载时使用 js 调用本机 java 代码的更好方法。 Refer this answer, though it's for ios, but the idea applys here too. 在下面查看我的答案以获得最小和简洁的解决方案 有谁知道如何使用 MAUI WebView 做到这一点? 【参考方案1】:

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

mWebView.setWebViewClient(new WebViewClient() 

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

【讨论】:

完美运行。您可以在加载前使用 mWebView.setVisibility(View.INVISIBLE)。加载完成后将其设置回 View.VISIBLE。我将它与这个初始屏幕一起使用:android-developers.blogspot.de/2009/03/… 这根本不是解决方案。调用此方法时不能保证页面已经加载。 这对 Google 来说是一个糟糕的设计。几乎在此操作完成时,您都希望围绕父 Activity 做一些事情,而不是 Web 视图本身。重写函数而不是订阅事件是一种常见的反模式,也是我不喜欢 android 开发的原因。 @Override在哪里? 此方法不保证加载完成,如果 url 加载需要一些中间 url 导航,则可以多次调用。所以这会被多次调用。然而,这是一种检查方式。【参考方案2】:

@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 文档中的警告:onPageStarted 将在嵌入框架的内容发生更改时被调用,即单击目标为 iframe 的链接。因此,这可能会扭曲这些情况下的逻辑。顺便说一句,@polen 的简化真的有效吗? 很好,从来没有注意到框架的东西。我还没有尝试过波兰人的代码..我可以保证的唯一工作就是我正在使用的上述代码。 只是一个小修正。它实际上是“public void onPageStarted (WebView view, String url, Bitmap favicon)”而不是“public void onPageStarted(WebView view, String url)” 不适用于一些从未完成加载的新网站...例如,“agoda.com”。你永远不会得到 onPageFinished 调用,因为它是一个重定向。 我看到 onPageFinished 在重定向期间被调用了两次。但是,根据 onPageFinished 的文档,您所说的“如果您在一个页面中有多个 iframe,您将有多个 onPageFinished(和 onPageStarted)”是不正确的:“此方法仅对主框架调用。”【参考方案3】:

我非常偏爱@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.
            
        
    );

【讨论】:

你的代码看起来不错。我一直在为从 html 数据而不是 url 加载的 webview 尝试相同的方法。但是,如果第一个 webview 快速加载并且在第二个 webview 开始加载之前,这个会触发 onPageFinished。正常情况。运行=1,运行=2,--运行=1,--运行=0。失败的异常场景 - running =1 , --running = 0, running =1 running =0 还有另一种情况,当某个事件由于某种原因未触发时,将永远无法到达 TODO 部分。所以你需要一个计时器来检查超时。或者,当您知道所有内容都已正确加载时,您可以在 javascript 中调用导出的 java 函数。像 documentReady() 之类的东西。 为什么不把running = 1; 放在onPageStarted() 中? @Choletski 因为1的最大值和大于1的数不是1。【参考方案4】:

我也找到了一个优雅的解决方案,但尚未对其进行严格测试:

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 方法外部调用它并使用处理程序在短时间内检查 - 如果您不想扩展 WebViewClient 类。 我相信这可能比接受的答案更好,你只需要检查 onError 就可以了。【参考方案5】:

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

mWebView.setWebChromeClient(new WebChromeClient()

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

                //change your progress bar
            


        );

顺便说一句,如果您只想显示一个覆盖方法 onPageFinished 的 Indeterminate ProgressBar 就足够了

【讨论】:

【参考方案6】:

我已将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() 永远不会被调用怎么办?【参考方案7】:

使用setWebViewClient() 并覆盖onPageFinished()

【讨论】:

【参考方案8】:

您可以通过webview 类中的getProgress 方法跟踪进度状态。

初始化进度状态

private int mProgressStatus = 0;

然后是这样加载的 AsyncTask:

private class Task_News_ArticleView extends AsyncTask<Void, Void, Void> 
    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();
        
    

【讨论】:

mProgressStatus = webview.getProgress();需要从 UI 线程调用。【参考方案9】:

感谢您的回答。它对我有帮助,但我必须根据自己的需要对其进行一些改进。我有几个 pagestarts 和 finish,所以我添加了一个计时器来检查是否在 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);
            
        

);

【讨论】:

【参考方案10】:

对于 Kotlin 用户:

webView.webViewClient = object : WebViewClient() 
            override fun onPageFinished(view: WebView?, url: String?) 
                // do your logic
            
        

有很多方法可以重写

【讨论】:

【参考方案11】:

这是一种利用Android's capability for JavaScript hooks 检测何时加载 URL 的新颖方法。使用这种模式,我们利用 JavaScript 对文档状态的了解在 Android 运行时生成本地方法调用。可以使用 @JavaScriptInterface 注释进行这些 JavaScript 可访问的调用。

此实现要求我们在 WebView 的设置上调用 setJavaScriptEnabled(true),因此它可能不适合,具体取决于您的应用程序的要求,例如安全问题。

src/io/github/cawfree/webviewcallback/MainActivity.java (Jelly Bean,API 级别 16)

package io.github.cawfree.webviewcallback;

/**
 *  Created by Alex Thomas (@Cawfree), 30/03/2017.
 **/

import android.net.http.SslError;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

/** An Activity demonstrating how to introduce a callback mechanism into Android's WebView. */
public class MainActivity extends AppCompatActivity 

    /* Static Declarations. */
    private static final String HOOK_JS             = "Android";
    private static final String URL_TEST            = "http://www.zonal.co.uk/";
    private static final String URL_PREPARE_WEBVIEW = "";

    /* Member Variables. */
    private WebView mWebView = null;

    /** Create the Activity. */
    @Override protected final void onCreate(final Bundle pSavedInstanceState) 
        // Initialize the parent definition.
        super.onCreate(pSavedInstanceState);
        // Set the Content View.
        this.setContentView(R.layout.activity_main);
        // Fetch the WebView.
        this.mWebView = (WebView)this.findViewById(R.id.webView);
        // Enable JavaScript.
        this.getWebView().getSettings().setJavaScriptEnabled(true);
        // Define the custom WebClient. (Here I'm just suppressing security errors, since older Android devices struggle with TLS.)
        this.getWebView().setWebViewClient(new WebViewClient()  @Override     public final void onReceivedSslError(final WebView pWebView, final SslErrorHandler pSslErrorHandler, final SslError pSslError)  pSslErrorHandler.proceed();  );
        // Define the WebView JavaScript hook.
        this.getWebView().addJavascriptInterface(this, MainActivity.HOOK_JS);
        // Make this initial call to prepare JavaScript execution.
        this.getWebView().loadUrl(MainActivity.URL_PREPARE_WEBVIEW);
    

    /** When the Activity is Resumed. */
    @Override protected final void onPostResume() 
        // Handle as usual.
        super.onPostResume();
        // Load the URL as usual.
        this.getWebView().loadUrl(MainActivity.URL_TEST);
        // Use JavaScript to embed a hook to Android's MainActivity. (The onExportPageLoaded() function implements the callback, whilst we add some tests for the state of the WebPage so as to infer when to export the event.)
        this.getWebView().loadUrl("javascript:" + "function onExportPageLoaded()  " + MainActivity.HOOK_JS + ".onPageLoaded(); " + "if(document.readyState === 'complete')  onExportPageLoaded();  else  window.addEventListener('onload', function ()  onExportPageLoaded(); , false); ");
    

    /** Javascript-accessible callback for declaring when a page has loaded. */
    @JavascriptInterface @SuppressWarnings("unused") public final void onPageLoaded() 
        // Display the Message.
        Toast.makeText(this, "Page has loaded!", Toast.LENGTH_SHORT).show();
    

    /* Getters. */
    public final WebView getWebView() 
        return this.mWebView;
    


res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<WebView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webView"
    android:layout_
    android:layout_
/>

基本上,我们附加了一个额外的 JavaScript 函数,用于测试文档的状态。如果它被加载,我们在 Android 的MainActivity 中启动一个自定义的onPageLoaded() 事件;否则,我们使用 window.addEventListener('onload', ...); 注册一个事件监听器,该监听器会在页面准备好后更新 Android。

由于我们是在调用 this.getWebView().loadURL("") 之后附加此脚本,因此我们可能根本不需要 'listen' 事件,因为我们只得到一旦页面已经加载,就有机会通过连续调用 loadURL 来附加 JavaScript 钩子。

【讨论】:

很棒的解决方案,通常有效。我在使用https://reddit.com/r/Nature(通常使用 Reddit)时遇到问题,当您单击某个线程并加载该线程时,我无法捕捉到该事件。你能帮帮我吗? @PrimožKralj 很高兴听到您在这方面取得了一些的成功...我不确定具体建议什么,但如果有任何类型的公共活动您知道会触发您可以挂钩的内容,例如当评论计数更新时,您可以将其用作来源。您是否考虑过直接点击 Reddit 的API 可以解决您的问题? 谢谢,我会再看看触发的事件并尝试连接其中一个。我知道 API,并将尝试在未来使用它来实现更强大的解决方案。谢谢!【参考方案12】:

仅仅为了显示进度条,“onPageStarted”和“onPageFinished”方法就足够了;但是如果你想要一个“is_loading”标志(以及页面重定向,......),这个方法可能会以非顺序执行,比如“onPageStarted > onPageStarted > onPageFinished > onPageFinished”队列。

但是通过我的简短测试(自己测试。),“onProgressChanged”方法值队列是“0-100 > 0-100 > 0-100 > ...”

private boolean is_loading = false;

webView.setWebChromeClient(new MyWebChromeClient(context));

private final class MyWebChromeClient extends WebChromeClient
    @Override
    public void onProgressChanged(WebView view, int newProgress) 
        if (newProgress == 0)
            is_loading = true;
         else if (newProgress == 100)
            is_loading = false;
        
        super.onProgressChanged(view, newProgress);
    

如果它是静态变量,还要在活动关闭时设置“is_loading = false”,因为活动可以在页面完成之前完成。

【讨论】:

【参考方案13】:

当调用 OnPageFinshed 方法或进度达到 100% 时,渲染器不会完成渲染,因此这两种方法都不能保证视图已完全渲染。

但是你可以从 OnLoadResource 方法中知道什么已经渲染,什么还在渲染。而且这个方法会被多次调用。

        @Override
        public void onLoadResource(WebView view, String url) 
            super.onLoadResource(view, url);
           // Log and see all the urls and know exactly what is being rendered and visible. If you wanna know when the entire page is completely rendered, find the last url from log and check it with if clause and implement your logic there.
            if (url.contains("assets/loginpage/img/ui/forms/")) 
                // loginpage is rendered and visible now.
               // your logic here.

            
        

【讨论】:

【参考方案14】:

正在加载带有SwipeRefreshLayoutProgressBar 的网址:UrlPageActivity.java:

    WebView webView;
    SwipeRefreshLayout _swipe_procesbar;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_url_page);


        String url = "http://***.com/";

        _swipe_procesbar = (SwipeRefreshLayout)findViewById(R.id.url_path_swipe_procesbar);

        _swipe_procesbar.post(new Runnable() 
                                  @Override
                                  public void run() 
                                      _swipe_procesbar.setRefreshing(true);
                                  
                              
        );

        webView = (WebView) findViewById(R.id.url_page_web_view);
        webView.getSettings().setJavaScriptEnabled(true);

        webView.setWebViewClient(new WebViewClient() 
            public void onPageFinished(WebView view, String url) 
                _swipe_procesbar.setRefreshing(false);
                _swipe_procesbar.setEnabled(false);
            
        );
        webView.loadUrl(url);
    

activity_url_page.xml:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/url_path_swipe_procesbar"
    android:layout_
    android:layout_>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools" android:layout_
            android:layout_
            tools:context="com.test.test1.UrlPageActivity">


            <WebView
                android:layout_
                android:layout_
                android:id="@+id/url_page_web_view" />
        </RelativeLayout>

</android.support.v4.widget.SwipeRefreshLayout>

【讨论】:

【参考方案15】:

这里有一个方法允许您注册一个Runnable,以便在特定网址完成加载后执行。我们将每个RunnableMap 中对应的URL String 相关联,并使用WebViewgetOriginalUrl() 方法来选择合适的回调。

package io.github.cawfree.webviewcallback;

/**
 *  Created by Alex Thomas (@Cawfree), 30/03/2017.
 **/

import android.net.http.SslError;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.util.HashMap;
import java.util.Map;

/** An Activity demonstrating how to introduce a callback mechanism into Android's WebView. */
public class MainActivity extends AppCompatActivity 

    /* Member Variables. */
    private WebView               mWebView;
    private Map<String, Runnable> mCallbackMap;

    /** Create the Activity. */
    @Override protected final void onCreate(final Bundle pSavedInstanceState) 
        // Initialize the parent definition.
        super.onCreate(pSavedInstanceState);
        // Set the Content View.
        this.setContentView(R.layout.activity_main);
        // Fetch the WebView.
        this.mWebView     = (WebView)this.findViewById(R.id.webView);
        this.mCallbackMap = new HashMap<>();
        // Define the custom WebClient. (Here I'm just suppressing security errors, since older Android devices struggle with TLS.)
        this.getWebView().setWebViewClient(new WebViewClient() 
            /** Handle when a request has been launched. */
            @Override public final void onPageFinished(final WebView pWebView, final String pUrl) 
                // Determine whether we're allowed to process the Runnable; if the page hadn't been redirected, or if we've finished redirection.
                if(pUrl.equals(pWebView.getOriginalUrl())) 
                    // Fetch the Runnable for the OriginalUrl.
                    final Runnable lRunnable = getCallbackMap().get(pWebView.getOriginalUrl());
                    // Is it valid?
                    if(lRunnable != null)  lRunnable.run(); 
                
                // Handle as usual.
                super.onPageFinished(pWebView, pUrl);
            
            /** Ensure we handle SSL state properly. */
            @Override public final void onReceivedSslError(final WebView pWebView, final SslErrorHandler pSslErrorHandler, final SslError pSslError)  pSslErrorHandler.proceed(); 
        );
        // Assert that we wish to visit Zonal's website.
        this.getWebView().loadUrl("http://www.zonal.co.uk/");
        // Align a Callback for Zonal; this will be serviced once the page has loaded.
        this.getCallbackMap().put("http://www.zonal.co.uk/", new Runnable()      @Override public void run()  /* Do something. */  );
    

    /* Getters. */
    public final WebView getWebView() 
        return this.mWebView;
    

    private final Map<String, Runnable> getCallbackMap() 
        return this.mCallbackMap;
    


【讨论】:

【参考方案16】:

使用它应该会有所帮助。`var currentUrl = "google.com" var partOfUrl = currentUrl.substring(0, currentUrl.length-2)

webView.setWebViewClient(object: WebViewClient()

override fun onLoadResource(WebView view, String url) 
     //call loadUrl() method  here 
     // also check if url contains partOfUrl, if not load it differently.
     if(url.contains(partOfUrl, true)) 
         //it should work if you reach inside this if scope.
      else if(!(currentUrl.startWith("w", true))) 
         webView.loadurl("www.$currentUrl")

      else if(!(currentUrl.startWith("h", true))) 
         webView.loadurl("https://$currentUrl")

      else  ...


 

override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) 
   // you can call again loadUrl from here too if there is any error.

//你还应该重写其他覆盖错误的方法,例如onReceiveError,以查看所有这些方法是如何一个接一个地调用的,以及它们在断点调试时的行为。 `

【讨论】:

【参考方案17】:

这将在他开始加载页面之前被调用 (并得到与onFinished()相同的参数)

@Override
public void onPageCommitVisible(WebView view, String url) 
   super.onPageCommitVisible(view, url);

【讨论】:

【参考方案18】:

Kotlin 解决方案 第一个解决方案是将 webviewclient 创建为私有类,它更有效。 另一方面,第二个解决方案是分拣机:)

第一个解决方案

class MainActivity : AppCompatActivity() 
  override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val webView : WebView = findViewById(R.id.webView)
    webView.webViewClient = MyWebViewClient()
 

private class MyWebViewClient : WebViewClient() 
    override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) 
        println("Load Started")
    
    override fun onPageFinished(view: WebView, url: String) 
        println("Load Finished")
    
  

第二个解决方案

class MainActivity : AppCompatActivity() 
  override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val webView : WebView = findViewById(R.id.webView)
    webView.webViewClient = object : WebViewClient() 
        override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) 
            println("Load Started")
        
        override fun onPageFinished(view: WebView, url: String) 
            println("Load Finished")
        
     
 

两种解决方案实际上相同。所以 onPageStarted 函数在页面开始加载时运行,而另一个挂起 onPageFinished 函数在页面完全加载时工作。您可能希望在 onPageFinished 函数中编写您的示例 loadFinishedRun() 函数。

迟到总比不到好

【讨论】:

一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助。 该评论来自评论。如果您对评论有任何问题,尽管您的关注表示赞赏​​,但最好将其标记出来。无论问题、答案或评论的内容如何,​​都遵循Code of Conduct 也很重要。

以上是关于如何监听 WebView 完成加载 URL?的主要内容,如果未能解决你的问题,请参考以下文章

延迟弹出对话框片段,直到其中的 webview 完成加载

WebView仿原生app页面切换效果

如何检查 WebView 的 URL?

WebView如何 监听url变化

想要在 webview android 中完成 url 加载后将 webview 重定向到其他意图

在 iPhone 上加载 url 时在 webview 中添加阴影