【问题标题】:Out of Memory on Bitmap Android位图 Android 内存不足
【发布时间】:2013-05-08 07:54:46
【问题描述】:

我想在 android 中实现这个 为此,我必须从资产文件夹加载图像,并在 xml 文件中创建两个 HorizontalScrollView 并在其中动态加载 ImageView。为了加载 ImageView 我正在使用此代码

LinearLayout myGallery = (LinearLayout) findViewById(R.id.mygallery);

try {
    String galleryDirectoryName = "gallery";
    String[] listImages = getAssets().list(galleryDirectoryName);
    for (String imageName : listImages) {
        InputStream is = getAssets().open(galleryDirectoryName + "/" + imageName);
        Bitmap bitmap = BitmapFactory.decodeStream(is);

        ImageView imageView = new ImageView(getApplicationContext());
        imageView.setLayoutParams(new ViewGroup.LayoutParams(100, 100));

        //   imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setImageBitmap(bitmap);

        LinearLayout.LayoutParams myGallery1=  new LinearLayout.LayoutParams(100, 100);
        myGallery1.setMargins(20, 0,  10, 0);

        //its is also working
        // imageView.setLayoutParams(myGallery1);       

        imageView.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                //   diplayImage.setImageBitmap(bitmap);
            }
        });

        Log.e("GalleryWithHorizontalScrollView", e.getMessage(), e);
    }

//重复上面的代码在第二个horizo​​ntalScrollView中加载imageView

LinearLayout myGallery2 = (LinearLayout) findViewById(R.id.mygallery2);

try {
    String galleryDirectoryName1 = "gallery2";
    String[] listImages2 = getAssets().list(galleryDirectoryName1);
    for (String imageName : listImages2) {
        InputStream is1 = getAssets().open(galleryDirectoryName1 + "/" + imageName);
        Bitmap bitmap1 = BitmapFactory.decodeStream(is1);

        ImageView imageView = new ImageView(getApplicationContext());
        imageView.setLayoutParams(new ViewGroup.LayoutParams(100, 100));

        //  imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setImageBitmap(bitmap1);

        LinearLayout.LayoutParams myGallery21=  new LinearLayout.LayoutParams(100, 100);
        myGallery21.setMargins(20, 40,  10, 0);

        //its is also working

        myGallery.addView(imageView,myGallery1);
    }
} catch (IOException e) {
    myGallery2.addView(imageView,myGallery21);
        }
} catch (IOException e) {
    Log.e("GalleryWithHorizontalScrollView", e.getMessage(), e);
}
}

如果我创建一个 Horizo​​ntalScrollView 并在其中加载图像视图,那么它可以正常工作,但对于第二个 Horizo​​ntalScrollView,它会在第 76 行给我错误

Bitmap bitmap1 = BitmapFactory.decodeStream(is1);

我的原木猫就是这个

05-14 11:13:26.000: E/AndroidRuntime(8350): FATAL EXCEPTION: main
05-14 11:13:26.000: E/AndroidRuntime(8350): java.lang.OutOfMemoryError
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:577)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:643)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at com.example.gallery.MainActivity.onCreate(MainActivity.java:76)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.app.Activity.performCreate(Activity.java:4470)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1053)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1934)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.app.ActivityThread.access$600(ActivityThread.java:128)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.os.Looper.loop(Looper.java:137)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at android.app.ActivityThread.main(ActivityThread.java:4517)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at java.lang.reflect.Method.invokeNative(Native Method)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at java.lang.reflect.Method.invoke(Method.java:511)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
05-14 11:13:26.000: E/AndroidRuntime(8350):     at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

  • 每张图片的尺寸是多少?不用的时候需要回收位图
  • 嗯,你也可以check out this link
  • 总共有 12 张图片,其中 4 张是 1024x780,其余的是 200x200 尺寸....在哪里调用 bitmap.recycle()....我只是在活动中加载图像 2 次

标签: android memory memory-management memory-leaks out-of-memory


【解决方案1】:

你可以找到你的答案here

您应该考虑的最重要的事情是优化您的缩略图的位图。 试试这个:

public static Bitmap decodeSampledBitmapFromInput(Context context,
        InputStream input, int reqWidth, int reqHeight) {

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

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeStream(input, null, options);
}

这里 reqWidth 是缩略图的宽度,与 reqHeight 相同。

对于 listView 尝试为您的位图实现缓存并尝试通过使用唯一键来获取它们可能是文件名(因为您不应该多次保存相同的图像)

【讨论】:

  • 嗯,你也可以check out this link
  • 也可以添加 options.inPurgeable = true; options.inInputShareable = true;
【解决方案2】:

您需要使用 BitmapFactory.Options

访问图像
 BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize =8;

然后

Bitmap bitmap1 = BitmapFactory.decodeStream(is1,null,options);

这样只有需要大小的位图被加载到内存中

更多信息请见Loading Large Bitmaps Efficiently

【讨论】:

    【解决方案3】:

    简单,不要加载太多图片...

    使用一些缓存,例如具有固定大小的 LRUCache。如果图像丢失,您必须先加载它们。应该提高性能并修复您的 OOME

    http://developer.android.com/reference/android/util/LruCache.html

    【讨论】:

    • google play 商店有很多图片。您可以向下滚动列表。 “简单,不要加载太多图像”不是答案。在这种情况下,延迟加载或 UIL 应该会有所帮助
    • 他们管理着内存,所以他们不会一次加载。这就是 LRU 发挥作用的地方
    猜你喜欢
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 2012-10-10
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多