Android图片加载OOM

本文探讨了Android应用在加载大图片时可能出现的内存泄漏(OOM)问题。通过在Activity中采用特定方法压缩图片背景以避免OOM,并指出即使使用Bitmap压缩,如果不妥善处理Activity生命周期,仍可能导致OOM。解决方案是在适当的时候调用finish()方法销毁Activity,让系统自动回收内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、在APP加载图片时如果在layout文件使用android:src=”@drawable/image”方式设置背景,在加载大图片时会出现内存泄漏的情况(即OOM),以下方法在Activity中设置背景图可以对图片进行有效的压缩。
2、使用bitmap方法对图片进行压缩后,跳转页面,Android虚拟机并未调用bitmap1.recycle()方法对垃圾进行回收,同时还有可能报错,提示bitmap.recycle()已经进行,不能再次执行。此时,由于页面没有被销毁,反复跳转页面还是会出现OOM,因此要根据Activity生命周期在其中调用finish()方法对页面进行销毁,页面垃圾会被自动回收,降低内存消耗。

package utils;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.view.View;

import java.io.IOException;
import java.io.InputStream;

/**
 * Created by lenovo on 2017/3/20.
 */

public class BitmapUtils {
    /*该方法将图片按宽高像素进行压缩,然后将压缩后的图片放大显示在APP界面中,如果像素设定过小,现示的图片会失真。*/
    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                         int reqWidth, int reqHeight) {
        // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        BitmapFactory.decodeResource(res, resId, options);
        // 调用上面定义的方法计算inSampleSize值
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        // 使用获取到的inSampleSize值再次解析图片
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }
    public static  int calculateInSampleSize(BitmapFactory.Options options,
                                             int reqWidth, int reqHeight) {
        // 源图片的高度和宽度
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            // 计算出实际宽高和目标宽高的比率
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
            // 一定都会大于等于目标的宽和高。
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }
    /*该方法以IO流的方式读取图片,将图片设置为背景图*/
    public static BitmapDrawable setBackgroundImage(Context context, int resId){
        BitmapFactory.Options opt = new BitmapFactory.Options();

        opt.inPreferredConfig = Bitmap.Config.RGB_565;

        opt.inPurgeable = true;

        opt.inInputShareable = true;
//获取资源图片
        InputStream is =context.getResources().openRawResource(resId);

        Bitmap bitmap = BitmapFactory.decodeStream(is,null, opt);

        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return new BitmapDrawable(context.getResources(),bitmap);
    }
    public static void setAndRecycleBackground(View v, int resID) {
        // 获得ImageView当前显示的图片
        Bitmap bitmap1 = null;
        if (v.getBackground() != null) {
            try {
                //若是可转成bitmap的背景,手动回收
                bitmap1 = ((BitmapDrawable) v.getBackground()).getBitmap();
            } catch (ClassCastException e) {
                //若无法转成bitmap,则解除引用,确保能被系统GC回收
                v.getBackground().setCallback(null);
            }
        }
        // 根据原始位图和Matrix创建新的图片
        v.setBackgroundResource(resID);
        // bitmap1确认即将不再使用,强制回收,这也是我们经常忽略的地方
        if (bitmap1 != null && !bitmap1.isRecycled()) {
            bitmap1.recycle();
        }
    }
    public static void releaseViewResouce(View view) {
        if (view== null) return;
        Drawable drawable = (BitmapDrawable)view.getBackground();
        if (drawable != null && drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            Bitmap bitmap = bitmapDrawable.getBitmap();
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值