内存错误尽管减少了android的图像大小

时间:2012-12-10 09:56:22

标签: android android-asynctask out-of-memory decode bitmapfactory

此应用程序没有任何问题,但速度太慢。它在一个UI线程上运行所有内容,当一个页面在gridView中加载了许多图像时,它会在页面加载之前花费很长时间。我使用名为“Processing Bitmaps Off the UI Thread

的Android文档中的代码修复了此问题

使用它现在加载网格视图页面的代码变化很快,之后你可以看到它在一个单独的后台线程中逐个加载每个小位图图像。

在这个使用AsyncTask进行多线程部分的代码中,它还使用了几种方法来减小图像大小以消除内存不足错误。我在此程序的先前单线程版本中使用的相同图像缩减方法。无论图像有多大,它都不应该大于200dp,通过图像缩小方法设置200dp。它适用于没有多线程的应用程序的旧版本,并且在新版本的应用程序中看起来很好。但是有一个奇怪的问题。

我现在遇到与BitmapFactory解码方法相关的内存不足错误。

如何发生这种情况是我开始使用许多较小的图像测试应用程序,并在其中放置一个大的10,000 X 10,000像素位图。这不应该导致问题,因为通过使用位图工厂选项减少了图像。

错误不会马上发生。该应用程序可以正常工作一段时间,但在四处移动并在活动之间返回之后。 3到5分钟后它会崩溃。

还有其他人有这样的问题吗?你能提供任何我可以查看的理由吗?或者帮我开始寻找正确的方向?

图像缩减代码如下所示,其下是logcat输出。

    class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
    private final WeakReference<ImageView> imageViewReference;
    private String data = "";

    public BitmapWorkerTask(ImageView imageView) {
        // Use a WeakReference to ensure the ImageView can be garbage collected
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    // Decode image in background.
    @Override
    protected Bitmap doInBackground(String... params) {
        data = params[0];
       // return imageProcessor(data);
        return decodeSampledBitmapFromResource(data, 100, 100);
    }

    // Once complete, see if ImageView is still around and set bitmap.
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (imageViewReference != null && bitmap != null) {
            final ImageView imageView = imageViewReference.get();
            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
            }
        }
    }
  }// end BitmapWorkerTask extends AsyncTask class

      public static Bitmap decodeSampledBitmapFromResource(String fileName, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(fileName, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;

    return BitmapFactory.decodeFile(fileName, options);


}//end decodeSampledBitmapfromresource method


public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {
    if (width > height) {
        inSampleSize = Math.round((float)height / (float)reqHeight);
    } else {
        inSampleSize = Math.round((float)width / (float)reqWidth);
    }
}
return inSampleSize;
}// end calculateInSampleSize method


Logcat

17:52:28.340: E/AndroidRuntime(7812): FATAL EXCEPTION: main
17:52:28.340: E/AndroidRuntime(7812): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.v.splitter/com.v.splitter.AudioViewer}: android.view.InflateException: Binary XML file line #63: Error inflating class <unknown>
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.access$600(ActivityThread.java:123)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
17:52:28.340: E/AndroidRuntime(7812): at android.os.Handler.dispatchMessage(Handler.java:99)
17:52:28.340: E/AndroidRuntime(7812): at android.os.Looper.loop(Looper.java:137)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.main(ActivityThread.java:4424)
17:52:28.340: E/AndroidRuntime(7812): at java.lang.reflect.Method.invokeNative(Native Method)
17:52:28.340: E/AndroidRuntime(7812): at java.lang.reflect.Method.invoke(Method.java:511)
17:52:28.340: E/AndroidRuntime(7812): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
17:52:28.340: E/AndroidRuntime(7812): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
17:52:28.340: E/AndroidRuntime(7812): at dalvik.system.NativeStart.main(Native Method)
17:52:28.340: E/AndroidRuntime(7812): Caused by: android.view.InflateException: Binary XML file line #63: Error inflating class <unknown>
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.createView(LayoutInflater.java:606)
17:52:28.340: E/AndroidRuntime(7812): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
17:52:28.340: E/AndroidRuntime(7812): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:255)
17:52:28.340: E/AndroidRuntime(7812): at android.app.Activity.setContentView(Activity.java:1835)
17:52:28.340: E/AndroidRuntime(7812): at com.v.splitter.AudioViewer.onCreate(AudioViewer.java:63)
17:52:28.340: E/AndroidRuntime(7812): at android.app.Activity.performCreate(Activity.java:4465)
17:52:28.340: E/AndroidRuntime(7812): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
17:52:28.340: E/AndroidRuntime(7812): ... 11 more
17:52:28.340: E/AndroidRuntime(7812): Caused by: java.lang.reflect.InvocationTargetException
17:52:28.340: E/AndroidRuntime(7812): at java.lang.reflect.Constructor.constructNative(Native Method)
17:52:28.340: E/AndroidRuntime(7812): at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.createView(LayoutInflater.java:586)
17:52:28.340: E/AndroidRuntime(7812): ... 24 more
12-17:52:28.340: E/AndroidRuntime(7812): Caused by: java.lang.OutOfMemoryError
17:52:28.340: E/AndroidRuntime(7812): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
17:52:28.340: E/AndroidRuntime(7812): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:483)
17:52:28.340: E/AndroidRuntime(7812): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
17:52:28.340: E/AndroidRuntime(7812): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
17:52:28.340: E/AndroidRuntime(7812): at android.content.res.Resources.loadDrawable(Resources.java:1937)
17:52:28.340: E/AndroidRuntime(7812): at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
17:52:28.340: E/AndroidRuntime(7812): at android.view.View.<init>(View.java:2785)
17:52:28.340: E/AndroidRuntime(7812): at android.view.View.<init>(View.java:2722)
17:52:28.340: E/AndroidRuntime(7812): at android.view.ViewGroup.<init>(ViewGroup.java:379)
17:52:28.340: E/AndroidRuntime(7812): at android.widget.RelativeLayout.<init>(RelativeLayout.java:174)
17:52:28.340: E/AndroidRuntime(7812): ... 27 more

1 个答案:

答案 0 :(得分:2)

仍然需要加载10,000x10,000图像才能使BitmapFactory调整大小。我建议将图像缩小。

无论如何,如果你使用了很多位图,请确保在完成它们后回收它们。它们消耗垃圾收集需要一段时间才能到达的本机资源。

bitmap.recycle();

请确保在回收后不使用Bitmap,因为会抛出异常。