这里,有个异步处理图片的方法,我直接把我这个类复制粘贴进来。注意内存要及时回收。android内存比较局限。



<span style="font-size:14px;">package com.commons.utils.image;import android.annotation.TargetApi;import android.content.Context;import android.graphics.*;import android.os.Build;import android.util.Log;import com.commons.config.GlobalConfig;import com.commons.utils.memory.MemoryUtils;import java.io.*;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;/** * 从DrawableUtil类中分离出来这个类,为了使代码看起来更加简洁明了 * 用于Bitmap处理的一些方法 */public class BitmapUtils {    public static final int ARGB8888_MODEL=4;//ARGB8888模式下消耗内存,为像素数乘以4个字节.    public static final int RGB565_MODEL=2;//RGB565模式下消耗内存,为像素数乘以4个字节.    /**     * 获取APP剩余可申请内存,判断是否够大,以手机分辨率为基础,进行计算图片处理所需要消耗的内存.     * @return     *     * !!!这里获取的不是手机的剩余内存而是APP的     */    public static boolean isBigSurpluseMemory(Context context)    {        boolean isbig=true;//默认        long appsurplusMe= MemoryUtils.getAppSurplusMe();//这里单位是Byte        long phonesurplusMe= MemoryUtils.getPhoneSurplusMe(context);//这里单位是Byte        long bitmapoptNeedmemory=GlobalConfig.scrwid*GlobalConfig.scrhei*ARGB8888_MODEL;//单位依旧是Byte        //在进行图片处理的时候会把图片分辨率缩小到屏幕分辨率大小,所以这里消耗内存的计算是以屏幕分辨率所谓基础的.        if(bitmapoptNeedmemory*2 > appsurplusMe)//为了其他考虑,剩余内存应该大于所需要内存的两倍        {            return false;        }        if(bitmapoptNeedmemory*2>phonesurplusMe)        {            return  false;        }//这里一定要判断手机剩余内存,上面的判断只是app的理论上的内存限制,而如果手机本身就已经没有内存了,        // 会有两种情况 1.自动清理一些内存  来给当前app用,2.本身就是内存太小,现在占内存的应用都是系统级别的清理不掉,那就坑了        // 举个例子:125M内存的手机上就会发生当手机时,我发现内存不够的时候,android的自动杀进程的机制就没法用了        //请看如下的我在410M的手机上运行的结果        return isbig;    }    /**     12-11 16:52:35.260      441-441/com.jsdx.zqysypt D/MemoryUtils.printMemoryInfo()﹕ 常规应用最大内存限制:64M 流氓应用最大内存限制:128M     12-11 16:52:35.270      441-441/com.jsdx.zqysypt D/MemoryUtils.printMemoryInfo()﹕ APP当前内存状态: 最大可申请内存:128MB 已申请内存:21MB 空闲内存:4MB     12-11 16:52:35.270      441-441/com.jsdx.zqysypt D/MemoryUtils.printMemoryInfo()﹕ 手机剩余内存:70.12109MB 手机总内存:410.54297MB     这里可以明显看出app剩余可申请的内存要大于手机的剩余内存的.当申请更多内存的时候android就会自动清理     */    /**     * 创建倒影图片     * @throws IOException     */    public static Bitmap createReflectedBitmap(Bitmap srcBitmap) {        if (null == srcBitmap) {            return null;        }        // The gap between the reflection bitmap and original bitmap.        final int REFLECTION_GAP = 4;        int srcWidth = srcBitmap.getWidth();        int srcHeight = srcBitmap.getHeight();        int reflectionWidth = srcBitmap.getWidth();        int reflectionHeight = srcBitmap.getHeight() / 2;        if (0 == srcWidth || srcHeight == 0) {            return null;        }        // The matrix        Matrix matrix = new Matrix();        matrix.preScale(1, -1);        try {            // The reflection bitmap, width is same with original's, height is half of original's.            Bitmap reflectionBitmap = Bitmap.createBitmap(                    srcBitmap,                    0,                    srcHeight / 2,                    srcWidth,                    srcHeight / 2,                    matrix,                    false);            if (null == reflectionBitmap) {                return null;            }            // Create the bitmap which contains original and reflection bitmap.            Bitmap bitmapWithReflection = Bitmap.createBitmap(                    reflectionWidth,                    srcHeight + reflectionHeight + REFLECTION_GAP,                    Bitmap.Config.ARGB_8888);            if (null == bitmapWithReflection) {                return null;            }            // Prepare the canvas to draw stuff.            Canvas canvas = new Canvas(bitmapWithReflection);            // Draw the original bitmap.            canvas.drawBitmap(srcBitmap, 0, 0, null);            // Draw the reflection bitmap.            canvas.drawBitmap(reflectionBitmap, 0, srcHeight + REFLECTION_GAP, null);            Paint paint = new Paint();            paint.setAntiAlias(true);            LinearGradient shader = new LinearGradient(                    0,                    srcHeight,                    0,                    bitmapWithReflection.getHeight() + REFLECTION_GAP,                    0x70FFFFFF,                    0x00FFFFFF,                    Shader.TileMode.MIRROR);            paint.setShader(shader);            paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));            // Draw the linear shader.            canvas.drawRect(                    0,                    srcHeight,                    srcWidth,                    bitmapWithReflection.getHeight() + REFLECTION_GAP,                    paint);            return bitmapWithReflection;        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    public static Bitmap revitionImageSize(String path, int max_w, int max_h) throws IOException {        BufferedInputStream in = new BufferedInputStream(new FileInputStream(                new File(path)));        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        BitmapFactory.decodeStream(in, null, options);        in.close();        int i = 0;        Bitmap bitmap = null;        while (true) {            if ((options.outWidth >> i <= max_w)                    && (options.outHeight >> i <= max_h)) {                in = new BufferedInputStream(                        new FileInputStream(new File(path)));                options.inSampleSize = (int) Math.pow(2.0D, i);                options.inJustDecodeBounds = false;                bitmap = BitmapFactory.decodeStream(in, null, options);                break;            }            i += 1;        }        return bitmap;    }    /**     *将Bitmap保存到本地     * @param bitmap     * @param imgurl imgurl   不带file了开头的路径,如:  /strange/sdcard/asdasd.jpg     */    public static void savePictureToLocal(Bitmap bitmap, String imgurl) {        FileOutputStream b = null;        File file = new File(imgurl);        file.getParentFile().mkdirs();// 创建文件夹        //对图片质量进行压缩,这样保存的图片就变小了        int yasuolv = 60;        try {            b = new FileOutputStream(imgurl);            bitmap.compress(Bitmap.CompressFormat.JPEG, yasuolv, b);// 把数据写入文件        } catch (FileNotFoundException e) {            e.printStackTrace();        } finally {            try {                b.flush();                b.close();                //bitmap.recycle();            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * 得到本地或者网络上的bitmap url - 网络或者本地图片的绝对路径,比如:     * <p/>     * A.网络路径: url="http://blog.foreverlove.us/girl2.png" ;     * <p/>     * B.本地路径:url="mnt/sdcard/photo/image.png";  不带 file: 头     * <p/>     * C.支持的图片格式 ,png, jpg,bmp,gif等等     *     * @param path     * @return     */    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)    public static Bitmap GetLocalOrNetBitmap(String path) {        final String  TAG="GetLocalOrNetBitmap";        Bitmap bitmap = null;        try {            BitmapFactory.Options options = new BitmapFactory.Options();            options.inJustDecodeBounds = true;            bitmap = BitmapFactory.decodeFile(path, options); //此时返回 bm 为空            options.inJustDecodeBounds = false; //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可            int hi = (int) (options.outHeight / (float) GlobalConfig.scrhei);//以屏幕高度作为显示依据            int wi = (int) (options.outWidth / (float) GlobalConfig.scrwid);//以屏幕高度作为显示依据            int be = 0;            if (wi > hi)                be = hi;            else                be = wi;            Log.d(TAG, "缩放比:"+be); //缩放之后            Log.d(TAG, "原图宽高:"+options.outWidth+" "+options.outHeight); //缩放之后            if (be <= 0)                be = 1;            options.inSampleSize = be; //重新读入图片,注意此时已经把 options.inJustDecodeBounds 设回 false 了            options.inPreferredConfig = Bitmap.Config.RGB_565;//使用RGB_565后会是内存降低一半但是,不适合decode带有透明区域的PNG            bitmap = BitmapFactory.decodeFile(path, options);            int w = bitmap.getWidth();            int h = bitmap.getHeight();            Log.d(TAG, "缩放后:宽"+w + " 高" + h); //缩放之后            Log.d(TAG, "RGB_565格式内存:"+bitmap.getByteCount() / 1024 + "KB");        }        catch (Exception ex)        {            if(bitmap!=null&&!bitmap.isRecycled())                bitmap.recycle();            System.gc();  //提醒系统及时回收        }        return bitmap;    }    //同上,最后一个参数可选,配置是否返回高色彩的Bitmap    //本地路径  不带 file: 头    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)    public static Bitmap GetLocalOrNetBitmap(String path, boolean isRGb_565) {        final String  TAG="GetLocalOrNetBitmap";        Bitmap bitmap = null;        try {            BitmapFactory.Options options = new BitmapFactory.Options();            options.inJustDecodeBounds = true;            bitmap = BitmapFactory.decodeFile(path, options); //此时返回 bm 为空            options.inJustDecodeBounds = false; //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可            int hi = (int) (options.outHeight / (float) GlobalConfig.scrhei);//以屏幕高度作为显示依据            int wi = (int) (options.outWidth / (float) GlobalConfig.scrwid);//以屏幕高度作为显示依据            int be = 0;            if (wi > hi)                be = hi;            else                be = wi;            Log.d(TAG, "缩放比:"+be); //缩放之后            Log.d(TAG, "原图宽高:"+options.outWidth+" "+options.outHeight); //缩放之后            if (be <= 0)                be = 1;            options.inSampleSize = be; //重新读入图片,注意此时已经把 options.inJustDecodeBounds 设回 false 了            if(isRGb_565)                options.inPreferredConfig = Bitmap.Config.RGB_565;//使用RGB_565后会是内存降低一半但是,不适合decode带有透明区域的PNG            bitmap = BitmapFactory.decodeFile(path, options);            int w = bitmap.getWidth();            int h = bitmap.getHeight();            Log.d(TAG, "缩放后:宽" + w + " 高" + h); //缩放之后            Log.d(TAG, "RGB_565格式内存:"+bitmap.getByteCount() / 1024 + "KB");        }        catch (Exception ex)        {            if(bitmap!=null&&!bitmap.isRecycled())                bitmap.recycle();            System.gc();  //提醒系统及时回收        }        return bitmap;    }    //同上,最后一个参数可选,配置是否返回高色彩的Bitmap    //本地路径  不带 file: 头    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)    public static Bitmap GetLocalOrNetBitmap(String path, boolean isRGb_565,int maxwidth,int maxheight) {        final String  TAG="GetLocalOrNetBitmap";        Bitmap bitmap = null;        try {            BitmapFactory.Options options = new BitmapFactory.Options();            options.inJustDecodeBounds = true;            Log.d("GetLocalOrNetBitmap",path);            bitmap = BitmapFactory.decodeFile(path, options); //此时返回 bm 为空            options.inJustDecodeBounds = false; //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可            int hi = (int) (options.outHeight / (float) maxwidth);//以指定宽度作为显示依据            int wi = (int) (options.outWidth / (float) maxheight);//以指定高度作为显示依据            int be = 0;            if (wi < hi)                be = hi;            else                be = wi;            Log.d(TAG, "缩放比:"+be); //缩放之后            Log.d(TAG, "原图宽高:"+options.outWidth+" "+options.outHeight); //缩放之后            if (be <= 0)                be = 1;            options.inSampleSize = be; //重新读入图片,注意此时已经把 options.inJustDecodeBounds 设回 false 了            if(isRGb_565)                options.inPreferredConfig = Bitmap.Config.RGB_565;//使用RGB_565后会是内存降低一半但是,不适合decode带有透明区域的PNG            bitmap = BitmapFactory.decodeFile(path, options);            int w = bitmap.getWidth();            int h = bitmap.getHeight();            Log.d(TAG, "缩放后:宽" + w + " 高" + h); //缩放之后            Log.d(TAG, "RGB_565格式内存:"+bitmap.getByteCount() / 1024 + "KB");        }        catch (Exception ex)        {            if(bitmap!=null&&!bitmap.isRecycled())                bitmap.recycle();            System.gc();  //提醒系统及时回收        }        return bitmap;    }    public static void createPath(String path) {        File file = new File(path);        if (!file.exists()) {            file.mkdir();        }    }    //传递两个参数即可 第一个是bitmap  第二个是目录名称,第二个参数为空时  保存在SD卡上    public static void saveMyBitmap(Bitmap bmp, String directory, String filename) {        String direc = "";        if (directory.length() < 1) {            direc = GlobalConfig.sdPath + "/";        } else {            direc = GlobalConfig.sdPath + "/" + directory + "/";            createPath(direc);        }        File f = null;        if (filename.length() < 1) {            try {                Date date = new Date();                DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH_mm_ss_");                filename = "www.njoki.com__" + format.format(date);            } catch (Exception e) {                filename = "未知";            }            f = new File(direc + filename + ".png");        } else {            f = new File(direc + filename + ".png");        }        FileOutputStream fOut = null;        try {            f.createNewFile();            fOut = new FileOutputStream(f);        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        //Bitmap bitmap = ((BitmapDrawable)mImageView.getDrawable()).getBitmap();        //bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);        bmp.compress(Bitmap.CompressFormat.PNG, 100, fOut);        try {            fOut.flush();        } catch (IOException e) {            e.printStackTrace();        }        try {            fOut.close();        } catch (IOException e) {            e.printStackTrace();        }    }}</span>


//上log


12-11 10:10:18.429 9782-9782/com.oki.lyw.activity D/lessenUriImage﹕ 缩放比:3
12-11 10:10:18.429 9782-9782/com.oki.lyw.activity D/lessenUriImage﹕ 原图宽高:3920 2204
12-11 10:10:18.870 9782-9782/com.oki.lyw.activity D/lessenUriImage﹕ 缩放后:宽1960 高1102
12-11 10:10:18.870 9782-9782/com.oki.lyw.activity D/lessenUriImage﹕ 内存:8437KB
12-11 10:14:39.684 12101-12101/com.oki.lyw.activity D/lessenUriImage﹕ 缩放比:3
12-11 10:14:39.684 12101-12101/com.oki.lyw.activity D/lessenUriImage﹕ 原图宽高:3920 2204
12-11 10:14:40.115 12101-12101/com.oki.lyw.activity D/lessenUriImage﹕ 缩放后:宽1960 高1102
12-11 10:14:40.115 12101-12101/com.oki.lyw.activity D/lessenUriImage﹕ RGB_565格式内存:4218KB


12-11 10:14:40.635 12101-12101/com.oki.lyw.activity D/imageloader消耗内存﹕ 4218KB
//从上面可以看出使用imageloader和我的这个方法消耗的内存是一致的






//上图


while(true) {


Runtime rt = Runtime.getRuntime();
try {
bitlist.add(BitmapUtils.lessenUriImage(input));
bitlist.add(BitmapUtils.lessenUriImage(input));
Log.d("TAG", "系统当前内存状态:已申请内存:" + rt.totalMemory() / 1024 + "KB 最大可申请内存:" + rt.maxMemory() / 1024 + "KB");
} catch (OutOfMemoryError error) {

Log.d("TAG", "系统当前内存状态:已申请内存:" + rt.totalMemory() / 1024 + "KB 最大可申请内存:" + rt.maxMemory() / 1024 + "KB"+" 空闲内存:"+rt.freeMemory()/1024+"KB");
Log.d("内存", "OOM了");
break;

}
};
bitlist=null;
System.gc();


if(true)
return ;

更多相关文章

  1. Android matrix 控制图片的旋转、缩放、移动
  2. android WebView 图片缩放功能小结
  3. Android 获取内存信息
  4. android使用inSampleSize、inScaled、inDensity、inTargetDensit
  5. Android:计算剩余内存
  6. 如何避免android上的进程的内存限制
  7. Android 的cpu 硬盘 内存 网络设置 系统信息 硬件信息
  8. android 内存缓冲机制:MemoryCache
  9. android避免decodeResource图片时占用太大的内存。

随机推荐

  1. 【华为认证HCIA】小白入门必看的VRRP协议
  2. 【深受启发篇】如何快速成为一个优秀的网
  3. 【网工收藏必备】从原理到配置,路由重发你
  4. 【网工必备】华为设备网络基础配置命令总
  5. 以一个ser2net软件包为例解读openwrt19.0
  6. 小技巧:SpringBoot项目如何让前端开发提高
  7. 【网工收藏必备】全网最全超详细BGP协议
  8. Java堆外内存排查小结
  9. 「网工必备」华为设备网络基础配置命令总
  10. 【网工收藏必备】全网最全超详细BGP协议