• 【转】解决Android因加载多个大图引起的OutOfMemoryError,内存溢出的问题


    本文来自:http://blog.csdn.net/wulianghuan/article/details/11548373,感谢原作者的分享。

    目标是读取SD卡中的图片并且展示出来

    主要思路是通过一个工具类来压缩来自sd卡中的图片,最后通过缓存机制来避免占用过多内存。

    Util.java

    package com.kale.socketactivity;
    
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    
    public class Util {
        
        /**
         * @param path
         * @return
         * @example Bitmap bitmap = BitmapFactory.decodeByteArray(Util.decodeBitmap(imagePath), 0, Util.decodeBitmap(imagePath).length);  
                    imageCache.put(imagePath, new SoftReference<Bitmap>(bitmap));  //这里用了软引用
         */
        public static byte[] decodeBitmap(String path) {
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inJustDecodeBounds = true;// 设置成了true,不占用内存,只获取bitmap宽高
            BitmapFactory.decodeFile(path, opts);
            opts.inSampleSize = computeSampleSize(opts, -1, 1024 * 800);
            opts.inJustDecodeBounds = false;// 这里一定要将其设置回false,因为之前我们将其设置成了true
            opts.inPurgeable = true;
            opts.inInputShareable = true;
            opts.inDither = false;
            opts.inPurgeable = true;
            opts.inTempStorage = new byte[16 * 1024];
            FileInputStream is = null;
            Bitmap bmp = null;
            ByteArrayOutputStream baos = null;
            try {
                is = new FileInputStream(path);
                //从文件中读取图片,可以换为别的方式
                bmp = BitmapFactory.decodeFileDescriptor(is.getFD(), null, opts);
                double scale = getScaling(opts.outWidth * opts.outHeight,
                        1024 * 600);
                Bitmap bmp2 = Bitmap.createScaledBitmap(bmp,
                        (int) (opts.outWidth * scale),
                        (int) (opts.outHeight * scale), true);
                bmp.recycle();
                baos = new ByteArrayOutputStream();
                bmp2.compress(Bitmap.CompressFormat.JPEG, 100, baos);
                bmp2.recycle();
                return baos.toByteArray();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    is.close();
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.gc();
            }
            return baos.toByteArray();
        }
    
        private static double getScaling(int src, int des) {
            /**
             * 48 目标尺寸÷原尺寸 sqrt开方,得出宽高百分比 49
             */
            double scale = Math.sqrt((double) des / (double) src);
            return scale;
        }
    
        public static int computeSampleSize(BitmapFactory.Options options,
                int minSideLength, int maxNumOfPixels) {
            int initialSize = computeInitialSampleSize(options, minSideLength,
                    maxNumOfPixels);
    
            int roundedSize;
            if (initialSize <= 8) {
                roundedSize = 1;
                while (roundedSize < initialSize) {
                    roundedSize <<= 1;
                }
            } else {
                roundedSize = (initialSize + 7) / 8 * 8;
            }
    
            return roundedSize;
        }
    
        private static int computeInitialSampleSize(BitmapFactory.Options options,
                int minSideLength, int maxNumOfPixels) {
            double w = options.outWidth;
            double h = options.outHeight;
    
            int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
                    .sqrt(w * h / maxNumOfPixels));
            int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
                    Math.floor(w / minSideLength), Math.floor(h / minSideLength));
    
            if (upperBound < lowerBound) {
                return lowerBound;
            }
    
            if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
                return 1;
            } else if (minSideLength == -1) {
                return lowerBound;
            } else {
                return upperBound;
            }
        }
    }

    使用方式:

    Bitmap bitmap = BitmapFactory.decodeByteArray(Util.decodeBitmap(imagePath), 0, Util.decodeBitmap(imagePath).length);  
                    imageCache.put(imagePath, new SoftReference<Bitmap>(bitmap));  

    实现类

    package com.pioneer.travel.util;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.ref.SoftReference;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.HashMap;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.BitmapFactory.Options;
    import android.graphics.drawable.Drawable;
    import android.os.Handler;
    import android.os.Message;
    import android.provider.MediaStore;
    import android.util.Log;
    import android.widget.ImageView;
    
    public class AsyncImageLoaderByPath {
        //SoftReference是软引用,是为了更好的为了系统回收变量
        private HashMap<String, SoftReference<Bitmap>> imageCache;
        private Context context;
        
        public AsyncImageLoaderByPath(Context context) {
            this.imageCache = new HashMap<String, SoftReference<Bitmap>>();
            this.context = context;
        }
        public Bitmap loadBitmapByPath(final String imagePath, final ImageView imageView, final ImageCallback imageCallback){
            if (imageCache.containsKey(imagePath)) {
                //从缓存中获取
                SoftReference<Bitmap> softReference = imageCache.get(imagePath);
                Bitmap bitmap = softReference.get();
                if (bitmap != null) {
                    return bitmap;
                }
            }
            final Handler handler = new Handler() {
                public void handleMessage(Message message) {
                    imageCallback.imageLoaded((Bitmap) message.obj, imageView, imagePath);
                }
            };
            //建立新一个获取SD卡的图片
            new Thread() {
                @Override
                public void run() {
                    Bitmap bitmap = BitmapFactory.decodeByteArray(Util.decodeBitmap(imagePath), 0, Util.decodeBitmap(imagePath).length);
                    imageCache.put(imagePath, new SoftReference<Bitmap>(bitmap));
                    Message message = handler.obtainMessage(0, bitmap);
                    handler.sendMessage(message);
                }
            }.start();
            return null;
        }
        //回调接口
        public interface ImageCallback {
            public void imageLoaded(Bitmap imageBitmap,ImageView imageView, String imagePath);
        }
    }
  • 相关阅读:
    [Go] golang http下返回json数据
    [Go] Golang练习项目-邮箱imap网页版客户端工具
    [Go] 提供http服务出现两次请求以及处理favicon.ico
    [Go] 转换编码处理网页显示乱码
    [Go] go转换gbk为utf8
    [Go] golang x.(type) 用法
    [GO] go语言中结构体的三种初始化方式
    [PHP] create_function() 代码注入问题已经被弃用
    [Git] 彻底删除github上的某个文件以及他的提交历史
    [javascript] vuejs的elementui实现父子iframe通信
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/3986246.html
Copyright © 2020-2023  润新知