android– 内存充满图片,可能是由Bitmap.compress引起的(格式,整数,流)

android– 内存充满图片,可能是由Bitmap.compress引起的(格式,整数,流),第1张

概述我的应用程序是一个Wifi聊天应用程序,您可以使用它与两个Android设备之间通过短信和快照相机图片进行通信并发送它们.图片存储在SD卡中.我曾经在几个发送的图像后抛出一个OutOfMemoryError,但是我通过发送来解决了这个问题options.inPurgeable=true;和options.inInputShar

我的应用程序是一个Wifi聊天应用程序,您可以使用它与两个Android设备之间通过短信和快照相机图片进行通信并发送它们.图片存储在SD卡中.

我曾经在几个发送的图像后抛出一个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, 0, fileSize - totalRead);                System.arraycopy(tempArray, 0, pictureByteArray, totalRead, lastRead);                totalRead += lastRead;                break;            }            lastRead = inStream.read(tempArray);            System.arraycopy(tempArray, 0, pictureByteArray, totalRead, lastRead);            totalRead += lastRead;        }        bufferedoutputstream bos = new bufferedoutputstream(new fileOutputStream(picturefile));        bos.write(pictureByteArray, 0, 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, 0, 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的图像是不好的做法?我应该先将它加载到内存中吗?

总结

以上是内存溢出为你收集整理的android – 内存充满图片,可能是由Bitmap.compress引起的(格式,整数,流)全部内容,希望文章能够帮你解决android – 内存充满图片,可能是由Bitmap.compress引起的(格式,整数,流)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1116894.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存