2014-01-28 4 views
0

Я exausted. Я работаю над этим весь день. В моем приложении у меня есть 100 ImageViews, но я получаю ошибку java.outofmemory, поэтому я решил декодировать и изменять размер файла, но я не могу заставить его работать. Может кто-нибудь взглянуть на код и предложить мне что-нибудь?Ошибка раздувания класса при попытке декодированияStream

MainActivity код: общественного класса MainActivity расширяет активность реализует OnClickListener {

ImageView display; 
int toPhone; 
private Context context; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    System.gc(); 
    context = this; 
    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); 
    Button setWall = (Button) findViewById(R.id.BsetWall); 
    image1.setOnClickListener(this); 
    image2.setOnClickListener(this); 
    image3.setOnClickListener(this); 
    image4.setOnClickListener(this); 
    image5.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(int resID) { 
    try { 
      // Decode image size 
      BitmapFactory.Options o = new BitmapFactory.Options(); 
      o.inJustDecodeBounds = true; 

я думаю, что в следующей строке у меня есть проблема, потому что это говорит значение локального переменного ВМРА не используется

  Bitmap bmp= BitmapFactory.decodeResource(context.getResources(), resID, o); 
      // 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.decodeResource(context.getResources(), resID, o2); 

    } finally { 

     } 
    } 

@Override 
public void onClick(View v) { 
    Bitmap bmpp; 
    switch (v.getId()){ 
    case R.id.WPimg1: 
     display.setImageResource(R.drawable.wal1); 
     toPhone = R.drawable.wal1; 

в следующей строке я пытаюсь расшифровать его (и я делаю это для каждого изображения)

  bmpp = decodeAndResizeFile(toPhone); 
     //Bitmap bmpp = decodeAndResizeFile(file); 
     break; 
    case R.id.WPimg2: 
     display.setImageResource(R.drawable.wal2); 
     toPhone = R.drawable.wal2; 
     bmpp = decodeAndResizeFile(toPhone); 
     display.setImageBitmap(bmpp); 
     break; 
    case R.id.WPimg3: 
     display.setImageResource(R.drawable.wal3); 
     toPhone = R.drawable.wal3; 
     bmpp = decodeAndResizeFile(toPhone); 
     break; 
    case R.id.WPimg4: 
     display.setImageResource(R.drawable.wal4); 
     toPhone = R.drawable.wal4; 
     bmpp = decodeAndResizeFile(toPhone); 
     break; 
    case R.id.WPimg5: 
     display.setImageResource(R.drawable.wal5); 
     toPhone = R.drawable.wal5; 
     bmpp = decodeAndResizeFile(toPhone); 
     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; 
    } 
    } 
    } 

вот мой Logcat

--- decoder->decode returned false 
Shutting down VM 
threadid=1: thread exiting with uncaught exception (group=0xb3adbba8) 
FATAL EXCEPTION: main 
Process: app.technozed.testwall, PID: 1250 
java.lang.RuntimeException: Unable to start activity ComponentInfo{app.technozed.testwall/app.technozed.testwall.MainActivity}: android.view.InflateException: Binary XML file line #304: Error inflating class <unknown> 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) 
at android.app.ActivityThread.access$800(ActivityThread.java:135) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:136) 
at android.app.ActivityThread.main(ActivityThread.java:5017) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:515) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) 
at dalvik.system.NativeStart.main(Native Method) 
Caused by: android.view.InflateException: Binary XML file line #304: Error inflating class <unknown> 
at android.view.LayoutInflater.createView(LayoutInflater.java:620) 
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56) 
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:669) 
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:694) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:755) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:758) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:758) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:492) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 
at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:290) 
at android.app.Activity.setContentView(Activity.java:1929) 
at app.technozed.testwall.MainActivity.onCreate(MainActivity.java:28) 
at android.app.Activity.performCreate(Activity.java:5231) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159) 
... 11 more 
Caused by: java.lang.reflect.InvocationTargetException 
at java.lang.reflect.Constructor.constructNative(Native Method) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
at android.view.LayoutInflater.createView(LayoutInflater.java:594) 
... 26 more 
Caused by: java.lang.OutOfMemoryError 
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:587) 
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:422) 
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:840) 
at android.content.res.Resources.loadDrawable(Resources.java:2110) 
at android.content.res.TypedArray.getDrawable(TypedArray.java:602) 
at android.widget.ImageView.<init>(ImageView.java:129) 
at android.widget.ImageView.<init>(ImageView.java:119) 
... 29 more 

ответ

1

Где у вас есть предупреждение «Значение локальной переменной ВМР не используется» в decodeAndResizeFile(), вы можете удалить «Bitmap BMP =» часть и оставьте это как:

BitmapFactory.decodeResource(context.getResources(), resID, o); 

Это потому, что этот вызов выполняется с o.inJustDecodeBounds = true. Когда это так, в объекте «o» возвращаются только размеры, и возвращается нулевая битовая карта (поэтому нет смысла ее хранить).

В вашем переключателе заявлении изменить каждый случай будет иметь следующий вид:

case R.id.WPimg1: 
    toPhone = R.drawable.wal1; 
    bmpp = decodeAndResizeFile(toPhone); 
    display.setImageBitmap(bmpp); 
    break; 

Так вот, вы декодируете ресурс в масштабном вниз растровое изображение, а затем назначить этот точечный рисунок на ImageView. Вы не хотите или нужно сделать это:

display.setImageResource(R.drawable.wal1); 

... так как вы рискуете в OutOfMemoryException и вы идете установить «дисплея» с масштабируемым битовым массивом в любом случае. Сделав эти изменения, ваш код работает для меня. Я вижу изображения предварительного просмотра обоев, а затем устанавливаю обои (не забудьте разрешение SET_WALLPAPER в манифесте).

Это, однако, не объясняет ваш логарифм, который кажется проблемой в onCreate(), накачивающем R.layout.activity_main. К концу вашего logcat он снова отображает OutOfMemoryError. Я могу воссоздать эту ошибку, если я назначу большой jpg для ImageView в XML (результаты OOM и поэтому макет не может быть завышен). Вы не можете масштабировать чертежи «на лету», когда они назначены в XML, поэтому создайте физически меньшие чертежи для использования в XML.

EDIT:

При нажатии на изображение, «дисплей» получает новое растровое изображение и старый, имеет право на GC.Вот один подход для освобождения памяти, используемой старым сразу же, не дожидаясь GC пнуть в:

Перемещение этого из OnClick(), чтобы быть переменной класса вместо:

Bitmap bmpp; //Reference to the same bitmap that 'display' is using 

Тогда в onClick():

Bitmap old_bm = null; //Reference to hold the old bitmap 
switch (v.getId()){ 
case R.id.WPimg1: 
    old_bm = bmpp; //Set to the bitmap currently being used by 'display' 
    toPhone = R.drawable.wal1; 
    bmpp = decodeAndResizeFile(toPhone); //'display' now has a new bitmap 
    display.setImageBitmap(bmpp); 
    if (old_bm != null) 
    { 
     old_bm.recycle(); //Recyle the old bitmap 
     old_bm = null;  //Clear the reference to allow GC to clean up fully 
    } 
    break; 
+0

он не работает на эмуляторе 16mb, но он работает на эмуляторе 1000 Мб. Но есть проблема, изображения очень маленькие, я хочу, чтобы они соответствовали экрану. –

+0

Вы можете указать свой ImageViews фиксированный размер, а затем установить тип шкалы, чтобы определить, как изображение нужно масштабировать, чтобы оно соответствовало: http: // developer.android.com/reference/android/widget/ImageView.ScaleType.html. Я думаю, что это будет случай, когда изображение будет достаточно маленьким, чтобы не вызвать OOM, но достаточно большое, чтобы иметь достойное разрешение при отображении. – NigelK

+0

Я так в своем Logcat, когда нажимаю на изображения, куча растет быстрее, чем GC frees memory 'Grow heap (frag case) до 46.873MB для 3240016-байтового выделения' ' Grow heap (frag case) до 47.902MB для 4320016- byte allocation' Могу ли я каким-то образом установить растровое изображение в нуль, когда я закончу работать с ним? –

Смежные вопросы