Android App OutOfMemory错误

时间:2016-05-07 23:55:02

标签: android out-of-memory

我正在编写一个需要大量内存的Android应用程序,并且遇到了内存不足的问题。该应用程序有两个活动。主要活动使用一系列按钮,这些按钮使用事件处理程序在第二个活动中将不同的图像加载到ImageViews中。当用户按下Android后退按钮时,应用程序将返回主活动。

我遇到的问题是,最终,应用程序因OutOfMemory错误而崩溃。

下图显示了我在应用程序的内存使用情况,因为我在两个活动之间来回切换。拍摄此屏幕截图后,我再次尝试通过其中一个按钮打开第二个活动,然后再次出现错误。 你会注意到最后一个驼峰远离其他驼峰。这是因为我停了一秒钟拍摄截图,期望下一次尝试会让它崩溃。如果我没有再次截图。

Android App Memory Usage Graph

我认为可以通过显式强制活动在不使用时释放内存来解决问题。这个问题是我不知道如何做到这一点,并且无法在线找到任何明确的解释,详细说明如何做到这一点。

以下是“图像视图”活动的代码示例:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ImageView;
import android.widget.TableRow;

import java.io.File;

public class ViewPost extends AppCompatActivity {
    Context appContext = this;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_image);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

    @Override
    protected void onResume() {
        super.onResume();

        new Thread(new Runnable() {
            @Override
            public void run() {
                final ImageView imgPhoto = (ImageView) findViewById(R.id.imgPhoto);
                final TableRow photoLayout = (TableRow) findViewById(R.id.photoLayout);

                // Get the width of the device screen.
                Point screenDimensionFinder = new Point();
                getWindowManager().getDefaultDisplay().getSize(screenDimensionFinder);
                final int screenWidth = screenDimensionFinder.x;

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        File imageFolder = new File(String.valueOf(appContext.getExternalFilesDir(
                                Environment.DIRECTORY_PICTURES)));
                        File photoFile = new File(imageFolder, "P" + Integer.toString(postId) +
                                ".jpg");
                        if(photoFile.exists()) {
                            Bitmap image = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
                            imgPhoto.setImageBitmap(resizeBitmap(image, screenWidth));
                        }
                        else {
                            photoLayout.setVisibility(View.GONE);
                        }
                    }
                });
            }
        }).start();
    }

    private Bitmap resizeBitmap(Bitmap image, int screenWidth)
    {
        // Resize the bitmap so that it fits on the screen, while preserving its aspect ratio.
        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();
        int imageNewHeight = (imageHeight * screenWidth) / imageWidth;
        image = Bitmap.createScaledBitmap(image, screenWidth, imageNewHeight, false);
        return image;
    }
}

2 个答案:

答案 0 :(得分:1)

您应该尝试使用此功能解码文件。此方法使用inSampleSize变量加载位图的缩小版本,从而减少内存消耗。

private Bitmap decodeFile(File f){
    Bitmap b = null;

        //Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;

    FileInputStream fis = new FileInputStream(f);
    BitmapFactory.decodeStream(fis, null, o);
    fis.close();

    int scale = 1;
    if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
        scale = (int)Math.pow(2, (int) Math.ceil(Math.log(IMAGE_MAX_SIZE / 
           (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
    }

    //Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    fis = new FileInputStream(f);
    b = BitmapFactory.decodeStream(fis, null, o2);
    fis.close();

    return b;
}

答案 1 :(得分:0)

我遇到了完全相同的问题。我通过广场使用毕加索来解决它。 。Picasso.with(的getContext())负载(imageResId).fit()centerInside()代入(ImageView的);

您必须更改加载方式,但它支持加载(文件f)。