Разобраться с java.lang.OutOfMemoryError?

я сделал приложение для установки обоев, на моем устройстве (Nexus 5) оно отлично работает, но на Galaxy TAB, Fame или даже на Optimus выдает ошибку java.lang.OutOfMemory. Я знаю, что мне не следует работать с таким количеством ImageView в одном приложении, или я должен? хорошо, проблема в том, что я не знаю, могу ли я как-то восстановить это приложение или я должен изменить всю структуру приложения.

Я покажу вам небольшую презентацию моего приложения

Основная активность:

 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)

Как видите, я уже добавил сборщики мусора, но это не особо помогает. Любые идеи? предложения?


person George Lungu    schedule 27.01.2014    source источник
comment
возможно, ваши изображения имеют очень высокое разрешение, что приводит к переполнению кучи и, следовательно, к OOM.   -  person Rat-a-tat-a-tat Ratatouille    schedule 27.01.2014
comment
Я сделал 2 набора изображений. первый - с оригинальными изображениями, второй - с небольшими изображениями, которые пользователь увидит в действии, это решило проблему, пока я не добавил больше изображений.   -  person George Lungu    schedule 28.01.2014


Ответы (2)


person    schedule
comment
Пока это выглядит правильно. Вы не дали объяснения своим действиям. Публикация только кода не помогает понять решение - person IAmGroot; 27.01.2014
comment
напишите эти функции и вызовите их. сначала получите растровое изображение и преобразуйте его в файл, и эта функция возвращает масштабируемое изображение, поэтому нехватка памяти будет уменьшена. в противном случае вы используете для этого библиотеку piccasso.. - person Dakshesh Khatri; 27.01.2014
comment
Файл file=new File(Uri.parse(String.valueOf(toPhone))) Bitmap bmpp = decodeAndResizeFile(file); - person Dakshesh Khatri; 27.01.2014
comment
я должен попробовать реализовать этот код @ user2968888, где я должен это вызвать? Файл file=new File(Uri.parse(String.valueOf(toPhone))) Bitmap bmpp = decodeAndResizeFile(file); - person George Lungu; 27.01.2014
comment
используйте здесь ::----› case R.id.WPimg1: toPhone = R.drawable.wall1; Файл file=new File(Uri.parse(String.valueOf(toPhone))) Bitmap bmpp = decodeAndResizeFile(file);display.setBitmapImage(bmpp); ломать; - person Dakshesh Khatri; 27.01.2014
comment
@user2968888 user2968888 я работал над этим весь день, кажется, у меня нет ошибок, но приложение не запускается, я создал еще один вопрос, не могли бы вы взглянуть здесь ссылка - person George Lungu; 28.01.2014

person    schedule
comment
этот File file=new File(Uri.parse(String.valueOf(toPhone))); говорит Конструктор File(Uri) не определен этот display.setImageBitmap(bm)(bmpp); говорит Левая часть присваивания должна быть переменной - person George Lungu; 27.01.2014
comment
под преобразованием изображений в файл вы имеете в виду реализовать это? public Bitmap decodeAndResizeFile(File f) { где мне это реализовать? я реализовал его до этого @Override public void onClick(View v) { - person George Lungu; 27.01.2014
comment
да, тогда вы реализуете это в коде, как предыдущий код, данный мне - person Dakshesh Khatri; 27.01.2014
comment
не могли бы вы взглянуть, я только что обновил код MainActivity, который я предоставил в вопросе. Что случилось? я получаю эти ошибки: этот файл файл = новый файл (Uri.parse (String.valueOf (toPhone))); говорит, что конструктор File(Uri) не определен this display.setImageBitmap(bm)(bmpp); говорит Левая часть присваивания должна быть переменной - person George Lungu; 27.01.2014
comment
хорошо, а как насчет того, чтобы File file=new File(Uri.parse(String.valueOf(toPhone))); получил файл конструктора (Uri) не определен - person George Lungu; 27.01.2014
comment
я только что обнаружил, что пропустил часть кода, где он определяет Uri --› Uri selectedImage = data.getData();, но теперь он говорит, что данные не могут быть разрешены - person George Lungu; 27.01.2014
comment
только для получения изображения с камеры или галереи. - person Dakshesh Khatri; 28.01.2014