应用壁纸时出现OutOfMemory错误

时间:2015-12-09 15:12:25

标签: android android-asynctask out-of-memory wallpaper android-wallpaper

尝试将壁纸应用到设备时,我遇到了OutOfMemoryError。

我正在使用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();
        }
    }
});

3 个答案:

答案 0 :(得分:0)

在Manifest文件

中的应用程序标记中添加android:largeHeap="true"
<application
        android:name=".MyApplication"
        android:largeHeap="true"
        ........ >
</application>

它会为您的应用增加分配的内存

官方文件说:

<强>机器人:largeHeap

  

是否应该使用大型创建应用程序的进程   达尔维克堆。这适用于为此创建的所有进程   应用。它只适用于第一个加载到的应用程序   处理;如果您使用共享用户ID来允许多个   要使用进程的应用程序,它们都必须使用此选项   一直或他们将有不可预测的结果。大多数应用应该   不需要这个,而应该专注于减少他们的整体   内存使用以提高性能。启用此功能也不会   保证固定增加可用内存,因为有些设备   受到总可用内存的限制。

     

要在运行时查询可用内存大小,请使用这些方法   getMemoryClass()getLargeMemoryClass()

答案 1 :(得分:0)

您要加载的位图的原始大小是多少?我自己遇到了同样的问题,我能够解决它的唯一方法是首先调整它的尺寸,然后加载它(我使用毕加索)将其缩小并将其设置为图像视图。

答案 2 :(得分:-1)

你在scale ...()方法中解码和解析位图一次,这是非常任务,内存明智,你抓住它并再次做而不调用它,它会消失明显缺乏缩放

使用巨大位图进行缩放的关键是在壁纸管理器中设置之​​前,手动进行逐步解析和缩放以及可能。零碎的作品是Canvas。 android.graphics.Canvas如果我没记错的话。