So I've got these long running server calls over what is basically OData going on in my Android application. The consumer of the calls uses .execute().get()
to wait for the response from the network thread (I know the proper way is to make the whole thing asynchronous and callback-based, but the app cannot function in any way without this data, and completely rearchitecting it to work in that way doesn't seem to provide any benefits).
So I found many snippets online where using the ProgressDialog
in combination with onPreExecute()
and onPostExecute()
as shown in the code sample below can be used to show a progress dialog while the AsyncTask
executes. I'm using exactly the samples provided, but what happens is that the call starts, it waits for the network transaction, then very quickly flashes and hides the progress dialog. It can sit for whole seconds waiting on the transaction and I know for a fact that it's waiting in the doInBackground()
, but the dialog just won't pop up until the very end, making it effectively useless.
In the code below the DoEvents()
bit is basically just a very short sleep. I've tried with and without it and there doesn't seem to be a difference, but it seemed worth trying.
class GetFromServerTask extends AsyncTask<String, Void, String>
{
private Context context;
private ProgressDialog dialog;
public GetFromServerTask(Context ctx) {
context = ctx;
dialog = new ProgressDialog(ctx);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog.setMessage("Loading...");
dialog.show();
DoEvents();
}
@Override
protected String doInBackground(String... parms) {
if(InOfflineMode)
return "notdeserializable";
String url = parms[0];
HttpURLConnection urlConnection = null;
try {
URL typedUrl = new URL(url);
urlConnection = (HttpURLConnection) typedUrl.openConnection();
//Add Authorization token
if(InDebugMode) {
urlConnection.addRequestProperty("AuthToken", AuthToken);
} else {
urlConnection.addRequestProperty("Authorization", "Bearer " + AuthToken);
}
urlConnection.addRequestProperty("Accept", "application/json");
DoEvents();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
byte[] contents = new byte[in.available()];
int bytesRead = 0;
String strContents = "";
while((bytesRead = in.read(contents)) != -1){
strContents += new String(contents, 0, bytesRead);
DoEvents();
}
if(strContents.startsWith("<HTML>"))
return "Error: Received unexpected HTML when connecting to service. Make sure you are not connected to a WIFI that requires authentication.";
return strContents;
} catch(UnknownHostException hex) {
return "Error: Could not find server address. Make sure you are connected to the internet. If you just changed connections (ie: turning WIFI on or off) it make take a minute to refresh";
}
catch(Exception ex) {
String msg = "Error: " + ex.getClass().getName() + ": " + ex.getMessage();
Log.e("TE", msg);
return msg;
} finally {
if(urlConnection != null)
urlConnection.disconnect();
}
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(dialog != null && dialog.isShowing())
dialog.dismiss();
DoEvents();
}
}
I've also tried the slightly different version suggested elsewhere on SO (shown below) with the same exact results:
protected void onPreExecute() {
dialog=ProgressDialog.show(context, "", "Loading...", true, false);
super.onPreExecute();
}
I've also tried taking the ProgressDialog
out of the AsyncTask
all together and showing it "outside" the task, as shown below. In this case it doesn't even appear.
ProgressDialog dialog = ProgressDialog.show(ServerAccessLayer.m_context, "", "Loading...", true, false);
String retVal = new GetFromServerTask(ServerAccessLayer.m_context).execute(url).get();
dialog.dismiss();
return retVal;