我曾经在几个发送的图像后抛出一个OutOfMemoryError,但是我通过发送来解决了这个问题
options.inPurgeable = true;
和
options.ininputShareable = true;
到BitmapFactory.decodeByteArray方法.这使得像素“可释放”,因此新图像可以使用存储器.因此,错误不再存在.
但是,内部存储器仍然充满了图像,并且出现“空间不足:手机存储空间不足”的警告.应用程序完成后,应用程序不再崩溃,但手机上没有更多内存.我必须在设置>中手动清除应用的数据.应用程序>管理应用程序
我尝试回收位图,甚至尝试显式清空应用程序的缓存,但它似乎没有做我期望的.
此函数通过TCP套接字接收图片,将其写入SD卡并启动我的自定义Activity PictureVIEw:
public voID receivePicture(String filename) { try { int fileSize = inStream.readInt(); Log.d("","fileSize:"+fileSize); byte[] tempArray = new byte[200]; byte[] pictureByteArray = new byte[fileSize]; path = Prefs.getPath(this) + "/" + filename; file picturefile = new file(path); try { if( !picturefile.exists() ) { picturefile.getParentfile().mkdirs(); picturefile.createNewfile(); } } catch (IOException e) { Log.d("","RecIEvepic - Kunde inte skapa fil.",e); } int lastRead = 0,totalRead = 0; while(lastRead != -1) { if(totalRead >= fileSize - 200) { lastRead = inStream.read(tempArray,fileSize - totalRead); System.arraycopy(tempArray,pictureByteArray,totalRead,lastRead); totalRead += lastRead; break; } lastRead = inStream.read(tempArray); System.arraycopy(tempArray,lastRead); totalRead += lastRead; } bufferedoutputstream bos = new bufferedoutputstream(new fileOutputStream(picturefile)); bos.write(pictureByteArray,totalRead); bos.flush(); bos.close(); bos = null; tempArray = null; pictureByteArray = null; setSentence("<"+filename+">",READER); Log.d("","path:"+path); try { startActivity(new Intent(this,PictureVIEw.class).putExtra("path",path)); } catch(Exception e) { e.printstacktrace(); } } catch(IOException e) { Log.d("","IOException:"+e); } catch(Exception e) { Log.d("","Exception:"+e); }}
这是PictureVIEw.它从SD卡上的文件创建一个byte [],将数组解码为Bitmap,压缩Bitmap并将其写回SD卡.最后,在Progress.ondismiss中,图片被设置为全屏imageVIEw的图像:
public class PictureVIEw extends Activity {private String filename;private ProgressDialog progress;public ImageVIEw vIEw;@OverrIDepublic voID onCreate(Bundle bundle) { super.onCreate(bundle); Log.d("","onCreate() PictureVIEw"); requestwindowFeature(Window.FEATURE_NO_Title); getwindow().setFlags(WindowManager.LayoutParams.FLAG_FulLSCREEN,WindowManager.LayoutParams.FLAG_FulLSCREEN); vIEw = new ImageVIEw(this); setContentVIEw(vIEw); progress = ProgressDialog.show(this,"","Laddar bild..."); progress.setondismissListener(new OndismissListener() { public voID ondismiss(DialogInterface dialog) { file file_ = getfileStreamPath(filename); Log.d("","SEtimage"); Uri uri = Uri.parse(file_.toString()); vIEw.setimageURI(uri); } }); new Thread() { public voID run() { String path = getIntent().getStringExtra("path"); Log.d("","path:"+path); file picturefile = new file(path); if(!picturefile.exists()) finish(); filename = path.substring(path.lastIndexOf('/') + 1); Log.d("","filename:"+filename); byte[] pictureArray = new byte[(int)picturefile.length()]; try { DatainputStream dis = new DatainputStream( new BufferedinputStream( new fileinputStream(picturefile)) ); for(int i=0; i < pictureArray.length; i++) pictureArray[i] = dis.readByte(); } catch(Exception e) { Log.d("",""+e); e.printstacktrace(); } /** * Passing these options to decodeByteArray makes the pixels deallocatable * if the memory runs out. */ BitmapFactory.Options options = new BitmapFactory.Options(); options.inPurgeable = true; options.ininputShareable = true; Bitmap pictureBM = BitmapFactory.decodeByteArray(pictureArray,pictureArray.length,options); OutputStream out = null; try { out = openfileOutput(filename,MODE_PRIVATE); /** * COMPRESS !!!!! **/ pictureBM.compress(CompressFormat.PNG,100,out); pictureBM = null; progress.dismiss(); } catch (IOException e) { Log.e("test","Failed to write bitmap",e); } finally { if (out != null) try { out.close(); out = null; } catch (IOException e) { } } } }.start();} @OverrIDe protected voID onStop() { super.onStop(); Log.d("","ONStop()"); Drawable oldDrawable = vIEw.getDrawable(); if( oldDrawable != null) { ((BitmapDrawable)oldDrawable).getBitmap().recycle(); oldDrawable = null; Log.d("","recycle"); } Editor editor = this.getSharedPreferences("clear_cache",Context.MODE_PRIVATE).edit(); editor.clear(); editor.commit(); }}
当用户按下后退键时,应用程序内的图片不再可用.只是存储在SD卡上.
在onStop()中,我回收旧的Bitmap甚至尝试清空应用程序的数据.仍然出现“低空间”警告.如何在不需要图像时不再分配内存?
编辑:似乎问题是压缩方法.如果压缩后的所有内容都被注释,问题仍然存在.如果我删除压缩,问题就会消失.压缩似乎分配了从未发布过的内存,每张图像只有2-3 MB.
解决方法 好的,我解决了.问题是,我正在传递一个OutputStream来压缩,这是一个流到应用程序内部存储器中私有文件的流.这就是我后来设置的图像.永远不会分配此文件.我没有得到我有两个文件:一个在SD卡上,一个在内存中,两个都有相同的名字.
现在,我只是将SD卡文件设置为ImageVIEw的图像.我从未将文件作为byte []读入内部存储器,因此从不将数组解码为位图,因此从不将位图压缩到内部存储器中.
这是新的PictureVIEw:
public class PictureVIEw extends Activity { public ImageVIEw vIEw; private String path; @OverrIDe public voID onCreate(Bundle bundle) { super.onCreate(bundle); Log.d("","onCreate() PictureVIEw"); path = getIntent().getStringExtra("path"); requestwindowFeature(Window.FEATURE_NO_Title); getwindow().setFlags(WindowManager.LayoutParams.FLAG_FulLSCREEN,WindowManager.LayoutParams.FLAG_FulLSCREEN); vIEw = new ImageVIEw(this); setContentVIEw(vIEw); Uri uri = Uri.parse( new file(path).toString() ); vIEw.setimageURI(uri); } @OverrIDe public boolean onKeyDown(int keyCode,KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { Log.d("","Back key pressed"); Drawable oldDrawable = vIEw.getDrawable(); if( oldDrawable != null) { ((BitmapDrawable)oldDrawable).getBitmap().recycle(); oldDrawable = null; Log.d("","recycle"); } vIEw = null; } return super.onKeyDown(keyCode,event); }}
将外部文件作为ImageVIEw的图像是不好的做法?我应该先将它加载到内存中吗?
@H_403_68@ 总结以上是内存溢出为你收集整理的android – 内存充满图片,可能是由Bitmap.compress引起的(格式,整数,流)全部内容,希望文章能够帮你解决android – 内存充满图片,可能是由Bitmap.compress引起的(格式,整数,流)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)