My AsyncTask is blocking block button element while downloading image and progress dialog is shown with delay - its shows for a while before image is shown, but downloading
The image download is indeed executed in the background thread, but with return task.get();
you're just waiting for it to finish, and that's what's blocking your main thread.
You should use onPostExecute()
as a callback for when the task has finished, so not just to dismiss the dialog but also to do what you need with the bitmap returned by doInBackground()
.
Old question, but have facing this issue. Yes, AsyncTask.get will block the UI thread until the result arrive, not giving processing space for your dialog to show, I've faced the same problem resolving with a more generic solution. Basically I create my AsyncTasks with a constructor receiving an AsyncTaskData (AsyncTaskData is a class that I have created, it's bellow) with all necessary data and a callback. I leave you my classes and an example.
AsyncTaskData.java
public class AsyncTaskData {
private Context activityContext;
private Object inputData; // whatever you want
private AsyncTaskCallback callback;
public AsyncTaskData(Context activityContext, Object inputData, AsyncTaskCallback callback) {
this.activityContext = activityContext;
this.inputData = inputData;
this.callback = callback;
}
// getters and setters
}
AsyncTaskCallback.java
public interface AsyncTaskCallback {
// method to be called when the task is finished (onPostExecute)
void onAsyncTaskTerminated(Object result);
}
So, for instance, if I have an AsyncTask to make login, it will be declared as follow:
public class LoginAsyncTask extends AsyncTask<Void, Void, Boolean> {
private AsyncTaskData asyncTaskData;
private ProgressDialog progressDialog;
public LoginAsyncTask (AsyncTaskData asyncTaskData) {
this.asyncTaskData = asyncTaskData;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(asyncTaskData.getActivityContext(), R.style.AppTheme);
progressDialog.show();
}
@Override
protected Boolean doInBackground(Void... voids) {
// if needed, get your data with asyncTaskData.getInputData()
AuthenticationData authData = (AuthenticationData) asyncTaskData.getInputData();
boolean loggedIn = // your heavy authentication process goes here
return loggedIn;
}
@Override
protected void onPostExecute(Boolean loggedIn) {
super.onPostExecute(searchResponse);
progressDialog.dismiss();
if(asyncTaskData.getCallback() == null) return;
asyncTaskData.getCallback().onAsyncTaskTerminated(loggedIn);
}
}
Finally, to use it just do this in your Fragment/Activity:
AsyncTaskData asyncTaskData = new AsyncTaskData(
getActivity(), // or this if you are calling from an Activity
new AuthenticationData("username", "password"),
result -> {
boolean loggedIn = (boolean) result;
// your login logic goeas here
});
new SearchAsyncTask(asyncTaskData)
.execute();
After many approaches, I ended up using this one because it's generic, leave the code clean and solve the problem of caling .get() method and blocking UI thread. Hope it helps.
It is because you are calling AsyncTask#get:
Waits if necessary for the computation to complete, and then retrieves its result.
You should perform whatever operation you need to use the image for within onPostExecute()