在Activity-A中,我使用Surfaceview和Bitmap作为背景。当我转到onPause时,我释放它并将其设置为null并创建一个显式GC。它工作正常。但是当我回到相同的Activity时 - 分配了近3MB的巨大堆来解码位图。这是因为我在GC之后解码位图。
我很好地回收了位图和GC流程。但我担心堆分配会增加,以便处理相同的位图。
当我移动下一个Activity时,我需要将它保存在某个不应该占用堆空间的地方,当我回来时我应该选择图像。知道如何实现这个目标吗?
以下是现有代码
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
ourSurfaceView.pause();
Log.i("DragDrop", "In pause drag drop");
backGround.release();
optionSelected.release();
backgoundImage.recycle();
backgoundImage=null;
backGround=optionSelected=null;
if (tts != null) {
Log.i("DragDrop", "In pause drag drop stop");
tts.stop();
tts.shutdown();
}
System.gc();
}
public void run() {
// TODO Auto-generated method stub
// Log.i("Notice", "In run of mybringback");
if(backgoundImage == null){
try {
Log.i("MyBringBack", "In run of mybringback");
backgoundImage = Bitmap.createScaledBitmap(getAssetImage(getApplicationContext(),"backgroundhomepage"), (int) dWidth, (int) dHeight, true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ourHolder = getHolder();
while (isRunning) {
// Log.i("DragDrop", "ourHolder.getSurface().isValid()" + ourHolder.getSurface().isValid() );
if (!ourHolder.getSurface().isValid()){
continue;
}
canvas = ourHolder.lockCanvas();
screenCenterX = dWidth / 2;
screenCenterY = dHeight / 2;
canvas.drawBitmap(backgoundImage, 0, 0, null);
if (imagePublishDone) {
if(!welcomeDone){
message = "Drop your wish to panda";
tts.speak(message, TextToSpeech.QUEUE_FLUSH, null);
welcomeDone=true;
}
moveImageInEllipticalPath();
} else {
initialImagePublish();
}
centreReached = false;
ourHolder.unlockCanvasAndPost(canvas);
}
}
public Bitmap getAssetImage(Context context, String filename) throws IOException {
AssetManager assets = getApplicationContext().getResources().getAssets();
InputStream buffer = null;
try {
buffer = new BufferedInputStream((assets.open("drawable/" + filename + ".png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
options.inPurgeable = true;
Bitmap temp = BitmapFactory.decodeStream(buffer, null, options);
Bitmap finalImage = Bitmap.createScaledBitmap(temp, (int) dWidth, (int) dHeight, true);
temp.recycle();
temp=null;
return finalImage;
}
答案 0 :(得分:0)
我认为解决问题的更好方法是在解码Bitmap
时使用inPurgeable
标志。
这样当系统需要回收内存时,它会在内部“回收”位图,但是当需要再次显示位图时,它会自动加载它。
[编辑]
您的代码存在一些问题。
inTempStorage
中的getAssetImage(...)
无用。这种“优化”应该为解码器提供临时计算所需的存储器。如果您不提供它,解码器将自行分配它。如果您通过多个解码分摊该分配的成本,这只是一种优化。但是,您的解决方案每次都会进行分配。不妨让解码器这样做,因为它确切地知道它需要多少内存。
看起来你在缩放你的位图时浪费了很多内存。 getAssetImage(...)
解码一个完整大小的图像,然后再缩放,返回和缩放。这是很多额外的工作和记忆。您应该考虑通过inSampleSize
对图像进行采样。要找出正确的采样因子,您可以使用inJustDecodeBounds。
最后,您对inPurgeable
的使用不正确。系统只能清除使用该选项解码的位图。但是,如上所述,您可以在加载可清除的位图后继续创建新的位图。此外,即使您修改了设计以便只加载正确的位图,我也不认为系统能够为您重新加载它,因为您使用的是decodeStream(...)
。流不能以通用方式重新打开和重绕,因此系统将无法重新读取该数据。尝试从文件解码。您还可以使用inInputShareable来更好地控制清除行为。