内存不足异常 + 分析hprof文件转储

10

这与以下问题有关:

java.lang.OutOfMemoryError at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)

我创建了相关的转储文件,并提供以下信息:

One instance of "byte[]" loaded by "<system class loader>" occupies 1,10,59,216
(51.02%) bytes. The memory is accumulated in one instance of "byte[]" 
 loaded by "<system class loader>".

Keywords byte[]
所以现在应该怎么办?我该如何解决这个问题? 我的list_objects [context] -inbound文件:
CLASS NAME                                                                 SHALLOW HEAP   RETAINED HEAP  
byte[11059200] @ 0xb4979590                                               |  1,10,59,216 |   1,10,59,216
mBuffer android.graphics.Bitmap @ 0xb3dc68d8                              |48            | 48
mBitmap android.graphics.drawable.BitmapDrawable @ 0xb3dbba60             | 72           | 144
mBackground android.widget.RelativeLayout @ 0xb3db3fc0                    |512           | 10,144
mBitmap android.graphics.drawable.BitmapDrawable$BitmapState @ 0xb3dc0068 |40          | 40
mBitmapState android.graphics.drawable.BitmapDrawable @ 0xb3dbba60        |72          |  144
referent java.lang.ref.WeakReference @ 0xb3dc2d68                         |24          |  24

我该如何解决内存问题?

我的 home_screen.java 文件。

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.home_page);
    main();
 private void main() {
    // TODO Auto-generated method stub
    
    
    final Button home;
    final Button aboutus;
    final Button contacts;
    final Button clients;
    final Button services;
    
    try
    {

    home = (Button)findViewById(R.id.btnHome);
    aboutus = (Button)findViewById(R.id.btnAboutus);
    clients = (Button)findViewById(R.id.btnClients);
    contacts = (Button)findViewById(R.id.btnContacts);
    services = (Button)findViewById(R.id.btnServices);
    
    home.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.home1);
            Drawable d = new BitmapDrawable(getResources(),b);              
            home.setBackgroundDrawable(d);
            System.gc();
            Intent myIntent = new Intent(Home_Screen.this, Button_Anime.class);
            startActivity(myIntent);
        }
    });
    aboutus.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.about1 );
            Drawable d = new BitmapDrawable(getResources(),b); 
            aboutus.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, AboutUs.class);
            startActivity(myIntent);
        }
    });
    clients.setOnClickListener(new  OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.clients1 );
            Drawable d = new BitmapDrawable(getResources(),b); 
            clients.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Clients.class);
            startActivity(myIntent);
        }
    });
    contacts.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.contact1);
            Drawable d = new BitmapDrawable(getResources(),b);
            contacts.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Contacts.class);
            startActivity(myIntent);
        }
    });
    services.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.services1 );
            Drawable d = new BitmapDrawable(getResources(),b);
            services.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Services.class);
            startActivity(myIntent);
        }
    });

    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

兄弟,看一下我的这个答案,应该会对你有所帮助。 - Pankaj Arora
我已经做了所有这些... 仍然得到相同的错误... 我的文件都是30-40kb大小,是的,我已经将堆设置为大@DevCarlsberg。 - user3214173
4个回答

4

这个方法是将您的图像进行下采样,以便在较小的屏幕上看起来很好,并且您不必将整个位图加载到内存中。

1)首先获取您将要显示的ImageView/屏幕的大小。

2)通过传递BitmapFactory.Options.inJustDecodeBounds读取您的位图的大小。这将为您提供位图的大小,而不是加载整个位图。

3)获取一个insample size。计算屏幕高度和宽度与图像高度和宽度的比率。使用最小值,使最大尺寸看起来很好。

4)最后使用下面的函数获取缩小的图像,这样就不会占用您的内存。

2)(代码)

BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, bitmapOptions);
int imageWidth = bitmapOptions.outWidth;
int imageHeight = bitmapOptions.outHeight;
inputStream.close();

4)(代码)

private Bitmap downscaleBitmapUsingDensities(final int sampleSize,final int imageResId)
  {
  final Options bitmapOptions=new Options();
  bitmapOptions.inDensity=sampleSize;
  bitmapOptions.inTargetDensity=1;
  final Bitmap scaledBitmap=BitmapFactory.decodeResource(getResources(),imageResId,bitmapOptions);
  scaledBitmap.setDensity(Bitmap.DENSITY_NONE);
  return scaledBitmap;
  }

2

这最多只是一个临时解决方案,来自链接的说法:“大多数应用程序不应该需要这样做,而应该专注于减少它们的整体内存使用。” - Sully

1

try the below code:

Resources res = getContext().getResources();
int id = R.drawable.image; 
Bitmap b = BitmapFactory.decodeResource(res, id);    
_img .setimagebitmap(b);

@DevCalsberg 这段代码不起作用,Eclipse 不接受它。Resources res = getContext().getResources(); home.setimagebitmap(b); 这两个代码都会产生错误。而且这段代码逻辑上难道不与我使用的代码相同吗? - user3214173

1
通常当我在低内存设备上遇到这种异常时,是因为我有一些分辨率太高的图片(很多kb)。 我遇到了一个奇怪的问题,因为我只使用了xhdpi和hdpi可绘制目录,在mdpi甚至ldpi设备上,hdpi转换到正确分辨率会引发此异常,因为无法调整图像大小。
这种情况在任何设备上都会发生吗?您能检查一下是否为这些低端设备准备了特定的图形吗?
无论如何,通过HPOF文件,您可以查看哪个活动/视图存在问题,或者至少可以看到出现问题的对象类型。 您需要分析所有这些数据(没有找到导致应用程序崩溃的资源的主要计划),以查看哪个部分存在问题。
希望这有所帮助,请随时提问。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接