0

尝试将壁纸应用到设备时出现 OutOfMemoryError。

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

3 回答 3

0

android:largeHeap="true"在清单文件中添加您的应用程序标签

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

它将增加分配给您的应用程序的内存

什么官方文件说:

机器人:大堆

是否应使用大型 Dalvik 堆创建应用程序的进程。这适用于为应用程序创建的所有进程。它仅适用于加载到进程中的第一个应用程序;如果您使用共享用户 ID 来允许多个应用程序使用一个进程,则它们都必须一致地使用此选项,否则它们将产生不可预知的结果。大多数应用程序不应该需要这个,而是应该专注于减少它们的整体内存使用以提高性能。启用此功能也不能保证可用内存的固定增加,因为某些设备受到其总可用内存的限制。

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

于 2015-12-09T16:15:02.023 回答
0

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

于 2015-12-09T20:09:55.873 回答
-1

您在 scale...() 方法中一次性解码和解析位图,这是非常有任务的,内存方面的,您抓住它并再次执行而不调用它,它会因明显缺乏缩放而消失

使用巨大位图进行缩放的关键是在墙纸管理器中进行设置之前零碎地进行解析和缩放,并且可能需要手动进行。零碎的工作是帆布。android.graphics.Canvas 如果我没记错的话。

于 2015-12-10T06:04:56.100 回答