0

У меня есть OutOfMemoryError при попытке применить обои к устройству.Ошибка OutOfMemory при использовании обоев

Я использую AsyncTask, и иногда он работает нормально, но иногда это происходит.

Может кто-нибудь помочь мне оптимизировать его еще больше? Заранее спасибо.

код AsyncTask:

public class ApplyWallpaper extends AsyncTask<Void, String, Boolean> { 
    private Context context; 
    private Activity activity; 
    private MaterialDialog dialog; 
    private Bitmap resource; 
    private View layout; 
    private boolean isPicker; 
    private Snackbar snackbar; 

    public ApplyWallpaper(Context context, MaterialDialog dialog, Bitmap resource, Boolean isPicker, View layout) { 
     this.activity = (Activity) context; 
     this.context = context; 
     this.dialog = dialog; 
     this.resource = resource; 
     this.isPicker = isPicker; 
     this.layout = layout; 
    } 

    @Override 
    protected Boolean doInBackground(Void... params) { 
     WallpaperManager wm = WallpaperManager.getInstance(context); 
     Boolean worked; 
     try { 
      wm.setBitmap(scaleToActualAspectRatio(resource)); 
      worked = true; 
     } catch (IOException e2) { 
      worked = false; 
     } 
     return worked; 
    } 

    @Override 
    protected void onPostExecute(Boolean worked) { 
     if (worked) { 
      dialog.dismiss(); 
      Util.showSimpleSnackbar(layout, 
        context.getString(R.string.set_as_wall_done), 1); 
     } else { 
      String retry = context.getResources().getString(R.string.retry); 
      snackbar = Snackbar 
        .make(layout, R.string.error, Snackbar.LENGTH_INDEFINITE) 
        .setAction(retry.toUpperCase(), new View.OnClickListener() { 
         @Override 
         public void onClick(View view) { 
          new ApplyWallpaper(context, dialog, resource, isPicker, layout); 
         } 
        }); 
      snackbar.setActionTextColor(context.getResources().getColor(R.color.accent)); 
      snackbar.show(); 
     } 
     if (isPicker) { 
      activity.finish(); 
     } 

    } 

    public Bitmap scaleToActualAspectRatio(Bitmap bitmap) { 
     if (bitmap != null) { 
      boolean flag = true; 
      int deviceWidth = activity.getWindowManager().getDefaultDisplay() 
        .getWidth(); 
      int deviceHeight = activity.getWindowManager().getDefaultDisplay() 
        .getHeight(); 
      int bitmapHeight = bitmap.getHeight(); 
      int bitmapWidth = bitmap.getWidth(); 
      if (bitmapWidth > deviceWidth) { 
       flag = false; 
       int scaledHeight = deviceHeight; 
       int scaledWidth = (scaledHeight * bitmapWidth)/bitmapHeight; 
       try { 
        if (scaledHeight > deviceHeight) 
         scaledHeight = deviceHeight; 
        bitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, 
          scaledHeight, true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
      if (flag) { 
       if (bitmapHeight > deviceHeight) { 
        int scaledHeight = deviceHeight; 
        int scaledWidth = (scaledHeight * bitmapWidth) 
          /bitmapHeight; 
        try { 
         if (scaledWidth > deviceWidth) 
          scaledWidth = deviceWidth; 
         bitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, 
           scaledHeight, true); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 
     return bitmap; 
    } 

} 

Обои ресурс загружается из:

Glide.with(context) 
.load(linkForWallpaper) 
.asBitmap() 
.into(new SimpleTarget<Bitmap>() { 
    @Override 
    public void onResourceReady(final Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { 
     if (resource != null) { 
      new ApplyWallpaper(context, dialogApply, resource, 
        false, layout, fab).execute(); 
     } 
    } 
}); 
+1

Где находится ресурс Bitmap? –

+0

@tinysunlight Вопрос отредактировал –

+0

Используйте инструменты мониторинга приложений Android Studio для анализа памяти в куче, которую использует ваше приложение, когда вы применяете обои, и найдите, какие объекты заполняют кучу вверх –

ответ

0

Добавить android:largeHeap="true" в прикладном тег внутри манифеста файла

<application 
     android:name=".MyApplication" 
     android:largeHeap="true" 
     ........ > 
</application> 

Это увеличит выделенную память для ваше приложение

Какой официальный документ говорит:

андроида: largeHeap

ли процессы вашего приложения должны быть созданы с большой Dalvik кучи. Это относится ко всем процессам, созданным для приложения . Это относится только к первой заявке, загруженной в процесс ; если вы используете общий идентификатор пользователя, чтобы разрешить нескольким приложениям использовать процесс, все они должны использовать этот параметр последовательно или они будут иметь непредсказуемые результаты. Большинство приложений должно не нуждаться в этом, и вместо этого следует сосредоточиться на сокращении общего использования памяти для повышения производительности. Включение этого также не гарантирует постоянное увеличение доступной памяти, поскольку некоторые устройства ограничены их общей доступной памятью.

Чтобы запросить доступный размер памяти во время работы, используйте методы getMemoryClass() или getLargeMemoryClass().

0

Каков первоначальный размер растрового изображения, которое вы загружаете? Я сам столкнулся с одной и той же проблемой, и единственный способ, которым я смог ее решить, - сначала изменить его на гораздо меньший размер, чем он первоначально был загружен (я использовал picasso), масштабируя его и устанавливая на изображение.

-1

Вы декодируетесь и анализировать растровое все в один раз в масштабе ...() метод, который чрезвычайно многозадачность, память мудра, вы поймете, что и делать снова, не называя, что и он уйдет с явным отсутствием масштабирования

Ключ к масштабированию с огромным растровым изображением состоит в том, чтобы выполнить разбор и масштабирование по частям и , вероятно, вручную, прежде чем устанавливать его в Wallpaper Manager. Поэтапная работа - Холст. android.graphics.Canvas, если я правильно помню.

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