Android 如何取消运行BitmapFactory.decodeFile()的异步任务并进行清理
在我的界面中,用户从不同数量的歌曲中进行选择,当选择一首歌曲时,我需要显示相关的背景图像。 用户需要在加载图像时保持对界面的控制,并且仍然能够更改歌曲 我目前的做法是使用AsyncTask 我正在使用以下方法执行它: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); 尝试取消前一个
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的并发性,我觉得大多数人都可以使用它的重要性的复习。你可能也想考虑一下。我有,谢谢,但我相信情况并非如此。