【问题标题】:Why my AsyncTask is not being properly cancelled?为什么我的 AsyncTask 没有被正确取消?
【发布时间】: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


    【解决方案1】:

    这似乎可行:使用全局变量 (changedir) 从 AsyncTask 的 onCancelled() 方法启动新的 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;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-13
      • 2021-08-03
      • 2021-03-17
      • 2010-10-12
      相关资源
      最近更新 更多