【问题标题】:Deal with java.lang.OutOfMemoryError?处理 java.lang.OutOfMemoryError?
【发布时间】:2014-01-27 21:27:29
【问题描述】:

我制作了一个壁纸集应用程序,在我的设备 (Nexus 5) 上效果很好,但在 Galaxy TAB、Fame 甚至 Optimus 上它会给出 java.lang.OutOfMemory 错误。我知道我不应该在一个应用程序中使用这么多的 ImageView,还是应该?好的,问题是如果我能以某种方式修复此应用程序,或者我应该更改整个应用程序结构,我不这样做。

我会给你看一个我的APP的小介绍

MainActivity:

 package app.technozed.cablewallpapershd;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.app.WallpaperManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

 public class MainActivity extends Activity implements OnClickListener {

ImageView display;
int toPhone;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    System.gc();
    toPhone = R.drawable.wal1;
    display = (ImageView) findViewById(R.id.WPdisplay);
    ImageView image1 = (ImageView) findViewById(R.id.WPimg1);
    ImageView image2 = (ImageView) findViewById(R.id.WPimg2);
    ImageView image3 = (ImageView) findViewById(R.id.WPimg3);
    ImageView image4 = (ImageView) findViewById(R.id.WPimg4);
    ImageView image5 = (ImageView) findViewById(R.id.WPimg5);
    ImageView image6 = (ImageView) findViewById(R.id.WPimg6);
    ImageView image7 = (ImageView) findViewById(R.id.WPimg7);
    ImageView image8 = (ImageView) findViewById(R.id.WPimg8);
    ImageView image9 = (ImageView) findViewById(R.id.WPimg9);
    ImageView image10 = (ImageView) findViewById(R.id.WPimg10);
    Button setWall = (Button) findViewById(R.id.BsetWall);
    image1.setOnClickListener(this);
    image2.setOnClickListener(this);
    image3.setOnClickListener(this);
    image4.setOnClickListener(this);
    image5.setOnClickListener(this);
    image6.setOnClickListener(this);
    image7.setOnClickListener(this);
    image8.setOnClickListener(this);
    image9.setOnClickListener(this);
    image10.setOnClickListener(this);
    setWall.setOnClickListener(this);
    }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

**public Bitmap decodeAndResizeFile(File f) {**
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f), null, o);

        // The new size we want to scale to
        final int REQUIRED_SIZE = 70;

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_SIZE
                    || height_tmp / 2 < REQUIRED_SIZE)
                break;
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {
    }
    return null;
}

@Override
public void onClick(View v) {
    switch (v.getId()){
    case R.id.WPimg1:
         display.setImageResource(R.drawable.wal1);
         toPhone = R.drawable.wal1;
         **File file=new File(Uri.parse(String.valueOf(toPhone)));
         Bitmap bmpp = decodeAndResizeFile(file);
        display.setImageBitmap(bm)(bmpp);**

         break;
    case R.id.WPimg2:
         display.setImageResource(R.drawable.wal2);
         toPhone = R.drawable.wal2;
         break;
    case R.id.WPimg3:
         display.setImageResource(R.drawable.wal3);
         toPhone = R.drawable.wal3;
         break;
    case R.id.WPimg4:
         display.setImageResource(R.drawable.wal4);
         toPhone = R.drawable.wal4;
         break;
    case R.id.WPimg5:
         display.setImageResource(R.drawable.wal5);
         toPhone = R.drawable.wal5;
         break;
    case R.id.WPimg6:
         display.setImageResource(R.drawable.wal6);
         toPhone = R.drawable.wal6;
         break;
    case R.id.WPimg7:
         display.setImageResource(R.drawable.wal7);
         toPhone = R.drawable.wal7;
         break;
    case R.id.WPimg8:
         display.setImageResource(R.drawable.wal8);
         toPhone = R.drawable.wal8;
         break;
    case R.id.WPimg9:
         display.setImageResource(R.drawable.wal9);
         toPhone = R.drawable.wal9;
         break;
    case R.id.WPimg10:
         display.setImageResource(R.drawable.wal10);
         toPhone = R.drawable.wal10;
         break;
    case R.id.BsetWall:
         try{
             WallpaperManager.getInstance(getApplicationContext()).setResource(toPhone);
             Toast.makeText(getApplicationContext(), "Wallpaper was set!", Toast.LENGTH_SHORT).show();
         } catch(IOException e) {
             e.printStackTrace();
             Toast.makeText(getApplicationContext(), "No privileges!", Toast.LENGTH_SHORT).show();
         }
         break;
    }
    }
    }

这是我的布局 XML

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".BasicScreenActivity"
android:layout_gravity="center_vertical"
android:background="@drawable/background" >
     <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="75dp"
    android:orientation="horizontal" />
 <ImageView 
    android:id="@+id/WPdisplay"
    android:src="@drawable/wall1"
    android:layout_width="wrap_content"
    android:layout_height="0dip"
    android:layout_gravity="center"
    android:layout_weight="1"
    android:contentDescription="@string/desc" />
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" >
<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
<ImageView 
    android:id="@+id/WPimg1"
    android:src="@drawable/w1"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView 
    android:id="@+id/WPimg2"
    android:src="@drawable/w2"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView  
    android:id="@+id/WPimg3"
    android:src="@drawable/w3"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView 
    android:id="@+id/WPimg4"
    android:src="@drawable/w4"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView 
    android:id="@+id/WPimg5"
    android:src="@drawable/w5"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView 
    android:id="@+id/WPimg6"
    android:src="@drawable/w6"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView 
    android:id="@+id/WPimg7"
    android:src="@drawable/w7"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView 
    android:id="@+id/WPimg8"
    android:src="@drawable/w8"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView 
    android:id="@+id/WPimg9"
    android:src="@drawable/w9"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />
<ImageView 
    android:id="@+id/WPimg10"
    android:src="@drawable/w10"
    android:layout_width="125dp"
    android:layout_height="125dp"
    android:padding="1dp"
    android:contentDescription="@string/desc" />

</LinearLayout>
</HorizontalScrollView>
               <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="25dp"
    android:orientation="horizontal" />
<Button
    android:id="@+id/BsetWall"
    android:layout_width="200dp"
    android:layout_height="28dp"
    android:background="@drawable/btn"
    android:layout_gravity="center"
    android:paddingBottom="8dp" />
</LinearLayout>

这是错误信息

   java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:353)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
at android.content.res.Resources.loadDrawable(Resources.java:1935)
at android.content.res.Resources.getDrawable(Resources.java:664)
at android.widget.ImageView.resolveUri(ImageView.java:611)
at android.widget.ImageView.setImageResource(ImageView.java:354)
at app.technozed.despicablemewallpapershd.MainActivity.onClick(MainActivity.java:334)
at android.view.View.performClick(View.java:4147)
at android.view.View$PerformClick.run(View.java:17161)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:4787)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
at dalvik.system.NativeStart.main(Native Method)

正如你所见,我已经添加了垃圾收集器,但它并没有真正的帮助。有任何想法吗?建议?

【问题讨论】:

  • 可能是您的图像分辨率非常高,导致堆溢出,从而导致 OOM。
  • 我制作了 2 组图像。第一个是原始图像,第二个是用户将在活动中看到的小图像,这解决了问题,直到我添加更多图像

标签: android memory-leaks wallpaper


【解决方案1】:
    public Bitmap decodeAndResizeFile(File f) {
            try {
                // Decode image size
                BitmapFactory.Options o = new BitmapFactory.Options();
                o.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(new FileInputStream(f), null, o);

                // The new size we want to scale to
                final int REQUIRED_SIZE = 70;

                // Find the correct scale value. It should be the power of 2.
                int width_tmp = o.outWidth, height_tmp = o.outHeight;
                int scale = 1;
                while (true) {
                    if (width_tmp / 2 < REQUIRED_SIZE
                            || height_tmp / 2 < REQUIRED_SIZE)
                        break;
                    width_tmp /= 2;
                    height_tmp /= 2;
                    scale *= 2;
                }
                BitmapFactory.Options o2 = new BitmapFactory.Options();
                o2.inSampleSize = scale;
                return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
            } catch (FileNotFoundException e) {
            }
            return null;
        }





Uri selectedImage = data.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };
            Cursor cursor = getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String picturePath = cursor.getString(columnIndex);

File file = new File(picturePath);// 
Bitmap bmpp = decodeAndResizeFile(file);

【讨论】:

  • 虽然这看起来是正确的。你没有解释你在做什么。仅发布代码对理解解决方案没有帮助
  • 编写这些函数并调用它。首先获取位图并转换为文件,这些函数返回可缩放的图像,因此内存不足将减少。否则你会为此使用 piccasso 库..
  • 文件 file=new File(Uri.parse(String.valueOf(toPhone))) 位图 bmpp = decodeAndResizeFile(file);
  • 我应该尝试实现此代码@user2968888 我应该在哪里调用它?文件 file=new File(Uri.parse(String.valueOf(toPhone))) 位图 bmpp = decodeAndResizeFile(file);
  • 在这里使用 ::----> case R.id.WPimg1: toPhone = R.drawable.wall1;文件 file=new File(Uri.parse(String.valueOf(toPhone))) 位图 bmpp = decodeAndResizeFile(file);display.setBitmapImage(bmpp);休息;
【解决方案2】:
Try to use this ur code that modifying me 

@Override
public void onClick(View v) {
           System.gc();
    switch (v.getId()){

  case R.id.WPimg1:

         toPhone = R.drawable.wall1;
 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);

         break;
    case R.id.WPimg2:

         toPhone = R.drawable.wall2;
 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.WPimg3:

         toPhone = R.drawable.wall3;

 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.WPimg4:

         toPhone = R.drawable.wall4;

 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.WPimg5:

         toPhone = R.drawable.wall5;

 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.WPimg6:

         toPhone = R.drawable.wall6;

 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.WPimg7:

         toPhone = R.drawable.wall7;

 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.WPimg8:

         toPhone = R.drawable.wall8;

 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.WPimg9:

         toPhone = R.drawable.wall9;

 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.WPimg10:

         toPhone = R.drawable.wall10;

 File file=new File(Uri.parse(String.valueOf(toPhone)));
 Bitmap bmpp = decodeAndResizeFile(file);
display.setImageBitmap(bm)(bmpp);
         break;
    case R.id.BsetWall:
         try{
                 WallpaperManager.getInstance(getApplicationContext()).setResource(toPhone);
             Toast.makeText(getApplicationContext(), "Wallpaper was set!", Toast.LENGTH_SHORT).show();
         } catch(IOException e) {
             e.printStackTrace();
             Toast.makeText(getApplicationContext(), "No privileges!", Toast.LENGTH_SHORT).show();
         }
         break;
    }
    }

【讨论】:

  • this File file=new File(Uri.parse(String.valueOf(toPhone))); 表示 构造函数 File(Uri) 未定义 this display.setImageBitmap(bm)(bmpp); 表示 赋值的左侧必须是变量 b>
  • 通过将图像转换为文件是指实现这个吗? public Bitmap decodeAndResizeFile(File f) { 我应该在哪里实现这个?我在这个 @Override public void onClick(View v) { 之前实现了它
  • 是的,那么您可以像以前给我的代码那样用代码实现它
  • 你能看看我刚刚更新了我在问题中提供的 MainActivity 代码。怎么了?我收到此错误:此 File file=new File(Uri.parse(String.valueOf(toPhone))); 构造函数 File(Uri) 未定义 this display.setImageBitmap(bm)(bmpp);说赋值的左边必须是变量
  • 好的,File file=new File(Uri.parse(String.valueOf(toPhone))); 得到 构造函数 File(Uri) 未定义
猜你喜欢
  • 2012-11-11
  • 2010-09-10
  • 2014-03-23
  • 2018-02-23
  • 2010-09-07
  • 2018-07-24
相关资源
最近更新 更多