在android中终止正在运行的下载异步任务

时间:2014-02-12 09:30:27

标签: android asynchronous android-fragments android-asynctask tabwidget

我正在处理图像下载程序,它是一个异步下载程序。每当需要在互联网上显示图像时我都会打电话

图像异步下载器(输入是目标图像视图,图像网址)

public class ImageLoader extends AsyncTask<Object, Void, Bitmap> {

    private static String TAG = "ImageLoader";
    public InputStream input;
    public ImageView view;
    public String imageURL;

    @Override
    protected Bitmap doInBackground(Object... params) {
        try {

            view = (ImageView) params[0];
            imageURL = (String) params[1];

            URL url = new URL(imageURL);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.setDoInput(true);
            connection.connect();
            input = connection.getInputStream();
            Bitmap myBitmap = BitmapFactory.decodeStream(input);
            return myBitmap;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (input != null)
                    input.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

    @Override
    protected void onPostExecute(Bitmap result) {
        if (result != null && view != null) {
            view.setImageBitmap(result);
            view.setBackgroundResource(android.R.color.transparent);
            view.getBackground().setAlpha(255);
        }
    }
}

当我切换到特定标签时,我的应用程序的结构是一个tabhost,例如在第4部分,有一个gridview,它将触发imageloader asynctask

片段:

gridView.setAdapter(new GalleryAdapter(getActivity() , images));

适配器:

public class GalleryAdapter extends BaseAdapter {
    private Context mContext;
    public ArrayList<GalleryImage> images;

    // Constructor
    public GalleryAdapter(Context c, ArrayList<GalleryImage> _images) {
        mContext = c;
        images = _images;
    }

    @Override
    public int getCount() {
        return images.size();
    }

    @Override
    public Object getItem(int position) {
        return images.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if( convertView == null ){
            convertView = (ImageView)new ImageView(mContext);
            int size = (int)(Utility.getScreenWidth(mContext) / 3) - 1; 
            AbsListView.LayoutParams params = new AbsListView.LayoutParams(size, size);
            convertView.setLayoutParams(params);
            convertView.setBackgroundResource(android.R.color.darker_gray);
            convertView.getBackground().setAlpha(204); // = 0.8 alpha
        }

        new ImageLoader().execute(convertView,images.get(position).thumbUrl);

        return convertView;
    }
}

我想知道在更改标签时有没有办法取消下载任务? (由于用户在完成所有下载之前都会离开选项卡,因此无需再下载)

1 个答案:

答案 0 :(得分:2)

可以随时通过调用cancel(boolean)取消任务。调用此方法将导致后续调用isCancelled()返回true。调用此方法后,onCancelled(Object)将在onPostExecute(Object)返回后调用,而不是doInBackground(Object[])为了确保尽快取消任务,您应该始终从isCancelled()定期检查doInBackground(Object[])的返回值,如果可能的话(例如在循环内)。

在您的情况下,doInBackground()代码中没有循环。事实上,如果通过读取缓冲的响应流将其转换为循环会更好。这样性能更高,并且您可以在循环中调用isCancelled()

示例:使用ByteArrayOutputStream读取块中的字节,并在循环中定期检查isCancelled()

protected Bitmap doInBackground(Object... params) {
            try {

                URL url = new URL(imageURL);
                HttpURLConnection connection = (HttpURLConnection) url
                        .openConnection();
                input = connection.getInputStream();

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] byteChunk = new byte[4096];
                int n;

                while ( (n = input.read(byteChunk)) > 0 ) {
                     if(isCancelled()) {
                        return null;
                     }
                     baos.write(byteChunk, 0, n);
                }

                Bitmap myBitmap = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.size());

                return myBitmap;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            } finally {
                try {
                    if (input != null)
                        input.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

   }

当然,您应该保留对AsyncTask对象的引用,以便能够对其调用cancel方法。

    private ImageLoader loader;
    ...
    ...
    loader = new ImageLoader();
    loader.execute();
    ...
    ...
    loader.cancel()