【Android】WebViewのロード完了までプログレスダイアログを表示する

WebViewに限ったことではないですが、重たい処理を実行中にローディング中であることを示すダイアログを表示する方法のまとめです。

画面の初期化やファイルの読み込み・書き込みなど様々な用途に応用できます。

今回はWebViewClientを継承したクラスを作ってonPageFinished()メソッドなどを実装します。

実装

プログレスダイアログの生成

変数(progressDialog)はメンバ変数、もしくはfinalで宣言する必要があります。理由はダイアログを閉じる時にメインスレッドとは別のスレッドからアクセスすることになるのでメソッド内のローカル変数だとエラーになります。

progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading...");
progressDialog.show();

プログレスダイアログの表示開始と主処理開始

HandlerクラスはUIスレッド(つまりメインスレッド)へRunnableを渡してUIや画面側を処理することが来ます。ここではWebViewのローディングと、その中のonPageFinishedメソッドでダイアログの停止を行っています。

// スレッド内でプログレスダイアログを閉じるためにHandlerを生成
final Handler handler = new Handler();

// スレッド処理
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    // ※ここで本来行いたい処理をする
                    webView.loadUrl("https://news.google.com/");
                }
            });
        } catch (Exception e) {
            Log.d("ERROR", e.getMessage());
        }
    }
}).start();

WebViewClientを継承したクラス

内部クラスで定義し、ページのロード処理が完了したらonPageFinishedメソッド内でダイアログを閉じるように処理を入れます。

これを生成した変数はsetWebViewClientでセットし、メインスレッドとは別でロードしてやります。

public final class MyViewClient extends WebViewClient {
    @Override
    public void onPageFinished(WebView view , String url){
        if(progressDialog.isShowing()) {
            progressDialog.dismiss();
        }

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                webView.stopLoading();
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                startActivity(intent);
                return false;
            }
        });
    }
}

ソースコード全体

MainActivity.java

ソースコード全体としは、以下のような感じです。

import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

    ProgressDialog progressDialog;

    WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // プログレスダイアログを生成・表示
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.show();

        // WebViewインスタンスを生成
        webView = findViewById(R.id.webviewTest);
        webView.clearCache(true);

        // WebViewClientを継承した独自クラスをセット
        webView.setWebViewClient(new MyViewClient());

        // スレッド内でプログレスダイアログを閉じるためにHandlerを生成
        final Handler handler = new Handler();

        // スレッド処理
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            webView.loadUrl("https://news.google.com/");
                        }
                    });
                } catch (Exception e) {
                    Log.d("ERROR", e.getMessage());
                }
            }
        }).start();
    }

    public final class MyViewClient extends WebViewClient {
        @Override
        public void onPageFinished(WebView view , String url){
            if(progressDialog.isShowing()) {
                progressDialog.dismiss();
            }

            webView.setWebViewClient(new WebViewClient() {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    webView.stopLoading();
                    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                    startActivity(intent);
                    return false;
                }
            });
        }
    }
}

実行結果

アプリケーションを実行するとまずはじめにダイアログが表示され、WebViewのローディングと同時にダイアログが消えて画面の操作が可能になります。

備考

WebViewのLoad処理でnet:ERR_CACHE_MISSが発生する場合

この問題はパーミッションが足りていないだけで、AndroidManifest.xml に以下を追加するだけで解消します。

<uses-permission android:name="android.permission.INTERNET" />

net:ERR_CACHE_MISSというエラーではPermissionの問題だとピンと来ずに少し嵌りかけたのでメモしておきます。

コメント

このブログの人気の投稿

docker-compose up で proxyconnect tcp: dial tcp: lookup proxy.example.com: no such host

docker-compose で起動したweb、MySQLに接続できない事象

【PHP】PHP_CodeSnifferを使う(コーディングルールのカスタマイズ)