我的AsyncTask阻塞块按钮元素,同时下载图像和进度对话框显示延迟 - 显示图像前显示一段时间,但下载需要很长时间,按钮被阻止(橙色)并且不显示对话框。
public Bitmap download(String url, ProgressBar progressbar) throws InterruptedException, ExecutionException {
BitmapDownloaderTask task = new BitmapDownloaderTask(progressbar);
task.execute(url);
return task.get();
}
class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
public BitmapDownloaderTask(ProgressBar progressbar) {
}
@Override
protected void onPreExecute() {
dialog = new ProgressDialog(ShowActivity.this);
dialog.setMessage("Loading");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
@Override
protected Bitmap doInBackground(String... Params) {
return imageLoader.getBitmap(params[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
dialog.dismiss();
}
}
在按钮监听器中,只需调用下载功能,进度参数是因为我在imageview中有进度条圆 - 该对话框仅用于测试,找到为什么有延迟和阻塞。在另一个应用程序中我使用runable并且线程和元素没有被阻止,但在教程中提到的AsyncTask是更好的解决方案。
答案 0 :(得分:13)
图像下载确实是在后台线程中执行的,但是return task.get();
只是等待它完成,这就是阻止你的主线程。
您应该使用onPostExecute()
作为任务完成时的回调,因此不仅要关闭对话框,还要使用doInBackground()
返回的位图执行所需操作。
答案 1 :(得分:2)
答案 2 :(得分:0)
旧问题,但已经遇到此问题。 是的,AsyncTask.get将阻塞UI线程,直到结果到达为止,没有为您的对话框提供处理空间来显示,我也遇到了使用更通用的解决方案来解决相同的问题。基本上,我使用接收到AsyncTaskData的构造函数创建AsyncTasks(AsyncTaskData是我创建的类,如下所示),其中包含所有必需的数据和回调。我给你我的课和一个例子。
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);
}
例如,如果我有一个AsyncTask进行登录,它将被声明为:
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);
}
}
最后,要使用它,只需在您的“片段/活动”中执行此操作:
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();
经过很多方法后,我最终使用了这一方法,因为它是通用的,将代码保持整洁,并解决了调用.get()方法和阻塞UI线程的问题。 希望对您有所帮助。