我创建了一个文件管理器,通过AsyncTask populate()
填充列表视图。如果文件夹中有几百个文件夹,则填充listview适配器需要几秒钟。但是,您可以在完全填充文件夹之前单击子文件夹。在这种情况下,填充过程(应该!)被取消,所有内容都被清除,并且新的AsyncTask开始使用新的填充过程。
我的问题是,如果你不等,有时文件夹中的一个元素会被带到子文件夹,在子文件夹中添加一个条目,该条目在文件夹中不存在。换句话说,旧的AsyncTask持续编写适配器,尽管我使用pop.isCancelled()
测试来测试它的结论。换句话说,尽管我检查了两个AsyncTasks同时运行。我尝试检查pop.getStatus() != Status.FINISHED
而不是pop.isCancelled()
,但它始终以RUNNING
状态失败。为什么我永远不会得到FINISHED
??。
我做错了什么(下面的代码)?我怎么能确定AsyncTask真的完成了?我理解dirs
变量可以在isCancelled()
中的doInBackground()
测试之后设置,但为什么调用进程没有检测到AsyncTask继续?
好的,你可以说我应该从第一个populate()
调用第二个onPostExecute()
,但是当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;
}
}
答案 0 :(得分:0)
看起来这很有效:使用全局变量(onCancelled()
)从AsyncTask的changedir
方法启动新的populate():
public void startPopulating(File dir) {
if (pop != null && pop.getStatus() != Status.FINISHED) {
changedir = dir;
pop.cancel(true);
} else {
changedir = null;
pop = new populate();
pop.run(dir);
}
}
class populate extends AsyncTask<Void, Boolean, Void> {
[....]
@Override
protected void onCancelled(Void args) {
super.onCancelled();
if (changedir != null && changedir.isDirectory()) {
pop = new populate();
pop.run(changedir);
changedir = null;
}
}
}