尝试将壁纸应用到设备时,我遇到了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();
}
}
});
答案 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如果我没记错的话。