【发布时间】:2014-02-25 19:28:36
【问题描述】:
我创建了一个文件管理器,它通过 AsyncTask populate() 填充列表视图。如果一个文件夹中有数百个文件夹,则填充 listview 适配器需要几秒钟。但是,您可以在文件夹完全填充之前单击子文件夹。在这种情况下,填充过程(应该!)被取消,一切都被清除,一个带有新填充过程的新 AsyncTask 开始。
我的问题是,如果你不等待,有时文件夹中的一个元素会被带到子文件夹中,在子文件夹中添加一个不存在但在文件夹中的条目。换句话说,尽管我使用pop.isCancelled() 测试来测试它的结论,但旧的 AsyncTask 仍然在编写适配器。换句话说,两个 AsyncTasks 同时运行,尽管我检查过。我试图检查pop.getStatus() != Status.FINISHED 而不是pop.isCancelled(),但它总是以RUNNING 状态失败。为什么我从来没有收到FINISHED??。
我做错了什么(下面的代码)?我如何确定 AsyncTask 真的完成了?我了解doInBackground()中的isCancelled()测试后可以设置dirs变量,但是为什么调用进程没有检测到AsyncTask继续呢?
好的,你可以说我应该从第一个的onPostExecute() 中调用第二个populate(),但是在取消 AsyncTask 时不会执行onPostExecute()。
这是我的简单代码。首先是调用过程,然后是AsyncTask的相关部分:
public void startPopulating(File folder) {
if (pop != null) {
pop.cancel(true);
while (pop != null && !pop.isCancelled()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
pop = null;
}
pop = new populate();
pop.run(folder);
}
class populate extends AsyncTask<Void, Boolean, Void> {
public void run (File dir) {
// Clean variables
if (dirs != null) dirs.clear();
if (files != null) files.clear();
basedir = dir;
execute();
}
@Override
protected void onProgressUpdate(Boolean... loading) {
if (!loading[0]) {
loadAdapterData(dirs, !dirmodified);
dirs.clear();
}
}
@Override
protected Void doInBackground(Void... params) {
dirs = new ArrayList<String>();
files = new ArrayList<String>();
String[] allfiles = basedir.list();
String thisfile;
publishProgress(true);
Arrays.sort(allfiles, String.CASE_INSENSITIVE_ORDER);
for (Integer i = 0; i < allfiles.length; i++) {
if (isCancelled()) break;
thisfile = allfiles[i];
if ((new File(basedir, thisfile)).isDirectory()) {
dirs.add(thisfile); // THIS LINE IS BEING EXECUTED AFTER THE TEST
} else {
files.add(thisfile);
}
if (i % 50 == 0 && dirs.size() > 0) publishProgress(false);
}
if (!isCancelled() && dirs.size() > 0) publishProgress(false);
return null;
}
}
【问题讨论】:
标签: android android-asynctask cancellation