我有3 AsyncTasks
和1 ProgressBar
。我希望当任何任务执行时,进度条都可见,当所有任务完成时,进度条是不可见的。
在Java中,有ExecutorService::isTerminated
来检查所有runnables是否已完成,但Android没有。
更新:3个任务同时执行。
图。
答案 0 :(得分:22)
漂亮的图形。但我担心没有建立机制。你必须自己实现它。您可以使用的解决方案很少 -
答案 1 :(得分:7)
尝试使用AsyncTask.getStatus()。这完全没问题。请参阅下面的示例代码。
List<AsyncTask<String, String, String>> asyncTasks = new ArrayList<AsyncTask<String, String, String>>();
AsyncTask<String, String, String> asyncTask1 = new uploadTask().execute(string);
AsyncTask<String, String, String> asyncTask2 = new downloadTask().execute(string);
AsyncTask<String, String, String> asyncTask3 = new createTask().execute(string);
asyncTasks.add(asyncTask1);
asyncTasks.add(asyncTask2);
asyncTasks.add(asyncTask3);
您可以稍后循环AsyncTaskList并找到每个任务的状态,如下所示。
for(int i=0;i<asyncTasks.size();i++){
AsyncTask<String, String, String> asyncTaskItem = (AsyncTask<String, String, String>)asyncTasks.get(i);
// getStatus() would return PENDING,RUNNING,FINISHED statuses
String status = asyncTaskItem.getStatus().toString();
//if status is FINISHED for all the 3 async tasks, hide the progressbar
}
答案 2 :(得分:2)
一个简单的解决方法是为每个AsyncTask使用三个布尔变量,然后相应地检查它们。
更好的方法是创建一个扩展AsynTask的单独类,并定义一个在onPostExecute中触发的回调接口。
答案 3 :(得分:1)
当你知道AsyncTask
何时结束(当onPostExecute
被调用时)时你知道了:
一个解决方案可能是创建一个方法setProgressBarVisible()
,它保持一个计数器,当第一次调用sets时可见,一个方法setProgressBarInvisible()
减少计数器,当零设置进度条不可见时。
答案 4 :(得分:1)
创建一个字段来保存所有任务:
private ArrayList<HtmlDownloaderTask> mTasks;
以这种方式开始您的任务:
HtmlDownloaderTask = new HtmlDownloaderTask(page.getHtml());
task.execute(page.getUrl());
//if you want parallel execution try this:
//task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,page.getUrl());
mTasks.add(task);
on MyAsyncTask的onPostExecute:
int unfinishedTasks = 0;
for (HtmlDownloaderTask myDT : mTasks){
if(!(myDT.getStatus() == AsyncTask.Status.FINISHED)){
unfinishedTasks++;
}
}
if (unfinishedTasks == 1){
//We are all done. 1 Because its the current one that hasnt finished post execute
callWhateverMethod();
}
答案 5 :(得分:0)
: - ?我认为这只是一个技巧。您将在每个onPostExecute
的{{1}}处返回一些消息并进行比较。 (例如,此消息可以包含时间)
答案 6 :(得分:0)
我只需在onPostExecute()
通知它,参考onPostExecute and 4 steps in the document for detail即可使用EventBus
进行订阅。
答案 7 :(得分:0)
自API级别24以来,我们引入了CompletableFuture的官方支持。
它也可以在Java 8中使用here。
可以使用简单的用法:
taskA.thenCombine(taskB).thenCombine(taskC)
答案 8 :(得分:0)
当您想在THREAD_POOL_EXECUTOR上运行一堆AsynTasks时,这是一个常见问题。这比仅调用.execute()
并一步一步完成所有任务要快得多。
因此,如果您有多个作业,并且对象之间互不依赖,请尝试在线程池上运行。
但是问题是:我怎么知道我所有的任务都完成了?
AsyncTask中没有内置方法,因此您应该采取一些解决方法。
在我的情况下,我向Asynctask类添加了一个静态Hashmap字段,以跟踪所有开始和完成的任务。作为地图的奖励,我总是可以知道当前正在执行哪个任务。
private static HashMap<Uri, Boolean> mapOfAttachmentTasks = new HashMap<>();
和简单的三种访问此地图的方法。 重要:它们应该同步
public static synchronized void addTask(Uri uri){
mapOfAttachmentTasks.put(uri, true);
}
public static synchronized void removeTask(Uri uri){
mapOfAttachmentTasks.remove(uri);
}
public static synchronized boolean isTasksEmpty(){
return mapOfAttachmentTasks.isEmpty();
}
您要在AsyncTask构造函数中向跟踪Map添加新项目,然后在onPostExecute()中将其删除:
public AttachmentTask(Uri uri) {
this.uri = uri;
addTask(uri);
}
@Override
protected void onPostExecute(Attachment attachment) {
removeTask(uri);
if(isTasksEmpty())
EventBus.getDefault().post(new AttachmentsTaskFinishedEvent(attachment));
}
每次完成任务时,它都会调用onPostEexecute,并检查它是否是最后一个任务。如果没有剩下的任务,请发送已完成的信号。
现在,在这里我使用EventBus将事件发送到Fragment,但是您可以使用回调。在这种情况下,您应该使用callbackMethod创建一个接口,您的Fragment(任何等待事件的UI组件)都应实现此接口并具有该方法。然后在AsyncTask构造函数中,将Fragment作为参数并保留对其的引用,以便在一切完成后可以调用它的回调方法。
但是我不喜欢这种方法。首先,您需要将片段(或任何其他UI)的引用保存在WeakReference包装器中,因为片段死时会发生内存泄漏(但仍保留在内存中,因为AsyncTask拥有它的引用)。 另外,您还需要进行大量检查,看起来像这样:
private boolean isAlive() {
return mFragmentWeakReference != null
&& mFragmentWeakReference.get() != null
&& mFragmentWeakReference.get().isAdded()
&& mFragmentWeakReference.get().getActivity() != null
&& !mFragmentWeakReference.get().getActivity().isFinishing();
是的,在生产中,您应该有点偏执,并进行所有这些检查:)
这就是为什么您可以使用EventBus以及用户界面已死的原因-
答案 9 :(得分:-1)
final ImageUploader _upload = new ImageUploader();
_upload.setValue(getApplicationContext(), _imagepath, _urlPHP);
_upload.execute();
Runnable _run;
Handler _h2;
_run = new Runnable() {
public void run() {
_h2 = new Handler();
_h2.postDelayed(this, 1000);
Toast.makeText(getApplicationContext(), "not finished", Toast.LENGTH_LONG).show();
if (_upload.getStatus() == AsyncTask.Status.FINISHED) {
Toast.makeText(getApplicationContext(), "finished", Toast.LENGTH_LONG).show();
_h2.removeCallbacks(_run);
}
}
};
_h2 = new Handler();
_h2.postDelayed(_run, 1);