Android1.5版本后,提供了AsyncTask这个类用来实现非阻塞的操作,比如下载列表数据等。AsyncTask虽然解决了UI主线程阻塞的问题,但是也有一个众所周知的问题:就是一旦运行了,就没办法停止下来。
如下图所示,系统正在获取当前目录下的子目录和图片的时候,数据还没完全加载完毕。这个时候,用户等不耐烦了点击某个子目录(比如DCIM这个目录),系统会启动一个新的AsyncTask去获取该子目录下的数据。但是由于之前的Task没法停止,我们常常会发现一个比较恼火的问题,就是原本属于上级目录的数据也会显示到当前子目录下来。

public class PhotoTask extends AsyncTask<String, File, Void>{
   
    @Override
    protected Void doInBackground(String... path) {
        File parent = new File(path[0]);
        if (parent.isDirectory()) {
            // 获取当前目录下的目录和文件
            File[] files = parent.listFiles();
            for (int j = 0; j < files.length; j++) {
                if(isCancelled()) return null;// Task被取消了,马上退出循环
               
                File file = files[j];  
                publishProgress(file );
            }
        }
    }

    @Override
    public void onProgressUpdate(File... files) {
        if(isCancelled()) return;   // Task被取消了,不再继续执行后面的代码
        .........
    }
}


public class PhotoGridView extends GridView implements OnItemClickListener{
    private PhotoTask task;  // 保持对Task的引用
   
    @Override
    public void onItemClick(AdapterView<?> adapter, View v, int position, long id) {
        if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) {
            task.cancel(true);  //  如果Task还在运行,则先取消它
        }
        ......
        // 启动新的任务
        task = new PhotoTask();
        task.execute(path);
        
    }
}
 通过以上的操作可以取消掉AsyncTask