Android 应用墙纸时发生OutOfMemory错误

Android 应用墙纸时发生OutOfMemory错误,android,android-asynctask,out-of-memory,wallpaper,android-wallpaper,Android,Android Asynctask,Out Of Memory,Wallpaper,Android Wallpaper,尝试将墙纸应用到设备时,我遇到OutOfMemory错误 我使用的是AsyncTask,有时工作正常,但有时会发生这种情况 有人能帮我进一步优化吗?提前谢谢 异步任务代码: public class ApplyWallpaper extends AsyncTask<Void, String, Boolean> { private Context context; private Activity activity; private MaterialDialog

尝试将墙纸应用到设备时,我遇到OutOfMemory错误

我使用的是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;
    }

}
public类ApplyWallpaper扩展异步任务{
私人语境;
私人活动;
私人材料对话;
私有位图资源;
私家景观布局;
私有布尔isPicker;
私人快餐店;
公共应用程序墙纸(上下文上下文、材质对话框、位图资源、布尔isPicker、视图布局){
this.activity=(activity)上下文;
this.context=上下文;
this.dialog=dialog;
这个资源=资源;
this.isPicker=isPicker;
this.layout=布局;
}
@凌驾
受保护的布尔doInBackground(Void…params){
WallpareManager wm=wallpareManager.getInstance(上下文);
布尔运算;
试一试{
wm.setBitmap(scaleToActualSpectratio(资源));
工作=真实;
}捕获(IOE2异常){
工作=假;
}
返回工作;
}
@凌驾
受保护的void onPostExecute(布尔工作){
如果(工作){
dialog.dismise();
Util.showsimplesnakbar(布局,
getString(R.string.set_as_wall_done),1);
}否则{
String retry=context.getResources().getString(R.String.retry);
snackbar=snackbar
.make(布局、R.string.error、Snackbar.LENGTH\u不确定)
.setAction(重试.toUpperCase(),新建视图.OnClickListener()){
@凌驾
公共void onClick(视图){
新的应用程序文件(上下文、对话框、资源、iPicker、布局);
}
});
setActionTextColor(context.getResources().getColor(R.color.accent));
snackbar.show();
}
如果(isPicker){
activity.finish();
}
}
公共位图比例实际光谱比率(位图){
if(位图!=null){
布尔标志=真;
int deviceWidth=activity.getWindowManager().getDefaultDisplay()
.getWidth();
int deviceHeight=activity.getWindowManager().getDefaultDisplay()
.getHeight();
int bitmapHeight=bitmap.getHeight();
int bitmapWidth=bitmap.getWidth();
if(位图宽度>设备宽度){
flag=false;
int scaledHeight=设备高度;
int scaledWidth=(scaledHeight*bitmapWidth)/bitmapHeight;
试一试{
如果(缩放高度>设备高度)
缩放高度=设备高度;
位图=位图。创建缩放位图(位图,缩放宽度,
缩放高度,真);
}捕获(例外e){
e、 printStackTrace();
}
}
国际单项体育联合会(旗){
如果(位图高度>设备高度){
int scaledHeight=设备高度;
int scaledWidth=(scaledHeight*位图宽度)
/位图高度;
试一试{
如果(缩放宽度>设备宽度)
scaledWidth=设备宽度;
位图=位图。创建缩放位图(位图,缩放宽度,
缩放高度,真);
}捕获(例外e){
e、 printStackTrace();
}
}
}
}
返回位图;
}
}
墙纸资源从以下位置加载:

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();
        }
    }
});
Glide.with(上下文)
.加载(链接壁纸)
.asBitmap()
.into(新的SimpleTarget(){
@凌驾

public void onResourceReady(最终位图资源,GlideAnimationAdd
android:largeHeap=“true”
在清单文件内的应用程序标记中

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


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

您以比例一次性解码和解析位图…()方法,这是非常任务化的,内存方面的,您可以捕捉到它,然后在不调用它的情况下再次执行,它将消失,明显缺乏可伸缩性


使用大型位图进行缩放的关键是在墙纸管理器中设置它之前,逐段进行解析和缩放,可能是手动进行。如果我没记错的话,逐段工作是Canvas.android.graphics.Canvas。

位图资源从何而来?@tinysunlight Question edited使用android Studio应用程序监控工具分析内存在应用墙纸时应用程序正在使用的堆中,并查找在堆中填充的对象upresource.recycle();bitmap=bitmap.createScaledBitmap(bitmap,scaledWidth,scaledHeight,true);以及在使用Glide加载图像时设置小尺寸。