为什么我的AsyncTask没有被正确取消?

时间:2014-02-25 19:28:37

标签: android android-asynctask cancellation

我创建了一个文件管理器,通过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;
    }   
}

1 个答案:

答案 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;
        }
    }
}