Android 如何取消运行BitmapFactory.decodeFile()的异步任务并进行清理

Android 如何取消运行BitmapFactory.decodeFile()的异步任务并进行清理,android,bitmap,android-asynctask,bitmapfactory,Android,Bitmap,Android Asynctask,Bitmapfactory,在我的界面中,用户从不同数量的歌曲中进行选择,当选择一首歌曲时,我需要显示相关的背景图像。 用户需要在加载图像时保持对界面的控制,并且仍然能够更改歌曲 我目前的做法是使用AsyncTask 我正在使用以下方法执行它: if (LoadBG!=null&&!LoadBG.isCancelled()) LoadBG.cancel(false); LoadBG = new loadBG(); LoadBG.execute((Object) diff.BGPath); 尝试取消前一个

在我的界面中,用户从不同数量的歌曲中进行选择,当选择一首歌曲时,我需要显示相关的背景图像。 用户需要在加载图像时保持对界面的控制,并且仍然能够更改歌曲

我目前的做法是使用AsyncTask

我正在使用以下方法执行它:

if (LoadBG!=null&&!LoadBG.isCancelled())
LoadBG.cancel(false);

LoadBG = new loadBG();
LoadBG.execute((Object) diff.BGPath);
尝试取消前一个任务(如果它仍在运行)并重新创建它

任务代码执行位图加载:

protected Boolean doInBackground(Object... param) {

        String pathName = param[0].toString();
        if (!pathName.equals(gfxStore.currentBGPath)) {

            currentBGLoaded = false;
            while(overlayOpacity!=255)
                Thread.yield();
            //set current bg
            if (this.isCancelled())
                return true;
            Bitmap d;
            try
            {
            d = gfxStore.factory.decodeFile(pathName,gfxStore.opts);
            }
            catch (OutOfMemoryError e)
            {
                System.gc();
                return true;
            }
            if (this.isCancelled())
            {
                d.recycle();
                d = null;
                System.gc();
                return true;
            }
            Bitmap s;
            try
            {
            s = gfxStore.scaleImageForCanvas(canvasWidth, canvasHeight,d );
            }
            catch (OutOfMemoryError e)
            {
                //XXX uuuugh
                System.gc();
                return true;
            }
            if (this.isCancelled())
            {
                d.recycle();
                d=null;
                s.recycle();
                s=null;
                System.gc();
                return true;
            }
            d.recycle();
            d=null;
            System.gc();
            gfxStore.currentBG = s;
            gfxStore.currentBGPath = pathName;
            wasChange = true;
        }
        else
            wasChange=false;
        return true;
    }
我已经把回收、置零、运行GC弄得一团糟,所有这些都试图取消当前任务,以便新创建的任务将有足够的内存用于分配,但是无论我做什么尝试,当我尝试太快运行太多(大约4/5次)时,我总是会遇到内存异常

图像是1024x768 jpg文件,要求分配1.5mb内存,我使用bitmapfactory选项:

opts.inPreferredConfig = Bitmap.Config.RGB_565;
    opts.inPurgeable = true;
    opts.inSampleSize = 1;

绝对-任何-建议都将不胜感激,我已经搜索了关于回收位图、置零、GCing、尝试使用可购买位图的所有信息。

您是否可以尝试使用互斥来序列化调用,以便只执行一个操作(即使由于某种原因取消了该操作)?下面是一个非常基本的方法。显然,您可以在doInBackground方法中执行更多的选择性锁定,但您已经了解了情况

static class DecodeLock extends Object {
}
static public DecodeLock lockObject = new DecodeLock();

// ...

protected Boolean doInBackground(Object... param) {
   synchronized (lockObject) {
      String pathName = param[0].toString();
          if (!pathName.equals(gfxStore.currentBGPath)) {

          //[..snip]
    }
 }

哇,它现在似乎工作得很好,没有任何错误。为了理解这一点,这是否会导致当前任务完成,并在下一个任务开始运行之前取消它(因为它正在等待同步)?是的,基本上每个异步任务都在单独的线程上运行(这是一种简化,但对于我们的目的来说已经足够了)。当一个线程点击“synchronized”关键字时,它将获得对“lockObject”的锁定,直到匹配的大括号出现在块的末尾。因此,如果另一个线程同时进入,它将在“synchronized”行阻塞,直到当前线程完成处理(无论它处理成功还是取消)。希望有帮助。+ 1的并发性,我觉得大多数人都可以使用它的重要性的复习。你可能也想考虑一下。我有,谢谢,但我相信情况并非如此。