0

デバイスに壁紙を適用しようとすると、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();
        }
    }
});
4

3 に答える 3

-1

scale...() メソッドで一度にビットマップをデコードして解析します。これは非常にタスクが多く、メモリに関しては賢明です。それをキャッチして、それを呼び出さずにもう一度実行すると、スケーリングが明らかに不足して消えてしまいます。

巨大なビットマップでスケーリングするための鍵は、壁紙マネージャーで設定する前に、解析とスケーリングを少しずつ、おそらく手動で行うことです。断片的な作品は Canvas です。私の記憶が正しければ android.graphics.Canvas です。

于 2015-12-10T06:04:56.100 に答える