Android   发布时间:2022-04-28  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了android – 内存充满图片,可能是由Bitmap.compress引起的(格式,整数,流)大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

我的应用程序是一个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, @R_460_10586@lRead = 0;
        while(lastRead != -1) {
            if(@R_460_10586@lRead >= fileSize - 200) {
                lastRead = instream.read(tempArray, 0, fileSize - @R_460_10586@lRead);
                System.arraycopy(tempArray, 0, pictureByteArray, @R_460_10586@lRead, lastRead);
                @R_460_10586@lRead += lastRead;
                break;
            }
            lastRead = instream.read(tempArray);
            System.arraycopy(tempArray, 0, pictureByteArray, @R_460_10586@lRead, lastRead);
            @R_460_10586@lRead += lastRead;
        }

        bufferedoutputstream bos = new bufferedoutputstream(new FiLeoutputStream(pictureFilE));
        bos.write(pictureByteArray, 0, @R_460_10586@lRead);
        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;

@Override
public void onCreate(Bundle bundlE) {
    super.onCreate(bundlE);
    Log.d("","onCreate() PictureView");

    requestWindowFeature(Window.FEATURE_NO_@R_450_10283@E);
    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_@R_450_10283@E);
        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引起的(格式,整数,流)所遇到的程序开发问题。

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

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:整数