0

Scenario: In my application, as I click on the button, it opens the dialog with WebView, loads some data (that involves copying, editing and loading the HTML file locally). The WebView is expected to display the HTML file created locally.

What is happening: Dialog takes a long time to open. It waits for at least file copying and editing part. The dialog opens when WebView starts loading the HTML file.

What I have tried: I tried calling these in main thread:

url = prepareLocalHtmlFile(dataKey); //Copy and edit html file and returns its path in local dir
webView.loadUrl(url); //Show the html file in WebView

Also tried in separate thread:

Thread mThread = new Thread() {
    @Override
    public void run() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                url = prepareLocalHtmlFile(dataKey); //Copy and edit html file and returns its path in local dir
                webView.loadUrl(url); //Show the html file in WebView
            }
        });
    }
};
mThread.start();

What I want: The dialog should open immediately as soon as I press the button and then all time-consuming operations should happen (copying, editing, loading HTML in webView). Please suggest how to achieve it.

user846316
  • 6,037
  • 6
  • 31
  • 40
  • Why do you use a background task just to do all the work on the main thread? – Henry Oct 21 '18 at 09:14
  • That's the first thing I did. I was calling prepareLocalHtmlFile(dataKey) and webView.loadUrl(url)) directly in the main thread only. But the dialog waits for a long time to open and load the WebView. Basically, what I am doing (as shown in the code above) is same as doing it in main thread. – user846316 Oct 21 '18 at 09:26

1 Answers1

0

After trying a bit more, I finally found the solution. Use AsyncTask.

I created a class which extends AsyncTask.

public class GenerateDataToDisplay extends AsyncTask<String, Integer, Boolean> {
    private Context context;
    private SQLiteDatabase appDb;

    public GenerateDataToDisplay(Context context, SQLiteDatabase appDb){
        this.context = context;
        this.appDb = appDb;
    }

    @Override
    protected Boolean doInBackground(String[] results) {
        return results.length > 0 && generateDataToDisplay(context, appDb, results[0]);
    }
}

Then execute this AsyncTask in the calling dialog as below:

new GenerateDataToDisplay(this, db)
        {
            @Override
            public void onPostExecute(Boolean result) {
                //Hide progress bar
                progressBar.setVisibility(View.GONE);
                //Display data
                textView.setText("Got it!!!"); 
            }
        }.execute(inputKey);

With this implementation, the dialog opens up immediately, progress bar displays, data load starts (AsyncTask). when the data is ready, the progress bar is gone and data is displayed.

It works fine for me so far. Feel free to comment to add another answer if you have better suggestions.

user846316
  • 6,037
  • 6
  • 31
  • 40
  • I believe async task is best way to go, if you want to you can also make use of onPreExecute(), onCancelled(), a method usable in doInBackground() called isCancelled() (for if they leave the app/activity, use this to stop any display or cancel execution) and publishProgress() to pass in data to display anything like a 0-100% complete progress bar, AsyncTasks are very useful and powerful things! :) – Brandon Oct 26 '18 at 14:04