ImageLoader

来源:互联网 发布:js点击按钮上传文件 编辑:程序博客网 时间:2024/06/13 06:15

概要:

ImageLoader,图片加载类。在Android中经常使用到图片加载。所以一个好的图片的加载类

对一个优秀的app非常重要。本文中是一个自定义的ImageLoader,是主要涉及两个方面:

一,图片的高效加载,主要通过BitmapFactory.Options来缩放图片。我们需要加载的图片如果

大于我们展示图片的控件大小,就会造成内存的浪费。这时我们可以通过Options.inSampleSize来

设置图片缩小的倍数。

二,图片的缓存策越,如果每次都从需要的图片都从网络中获取,会浪费用户的流量,而且不高效。

这里使用LruCache实现内存缓存。DiskLruCache实现磁盘缓存。


分析:

一,图片的高效的加载。

我们在使用BitmapFactory加载图片是,会直接或间接的使用Option。通过设定Option.inSampleSize

来控制加载图片的大小。在Android官方文档中,inSampleSize推荐为2的指数,例如有一张1024*1024*4

(4MB)的图片,当inSampleSize=2时,加载后的Bitmap为512*512*4(1MB),所占内存为原来的1/4。

二,图片的缓存策越,我们加载图片的策越:

1,读取内存缓存,先从内存缓存(MemoryLRUCache)中,查找所需图片。不为null则返回。为null则

执行下一步。

2,读取本地缓存,从磁盘缓存(DiskLRUCache)中,查找所需图片,不为nulll则返回,并将Bitmap添加

到内存缓存(MemoryLRUCache),为nul则执行下一步。

3,读取网络资源,从网络中下载图片到本地即磁盘缓存,然后读取本地缓存。


应用:

一,高效加载图片。

1,从resource中加载图片。

    public Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {        final BitmapFactory.Options options = new BitmapFactory.Options();        // 第一次加载只获取图片的信息        options.inJustDecodeBounds = true;        BitmapFactory.decodeResource(res, resId, options);        // 计算inSampleSize        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);        // 正式加载Bitmap        options.inJustDecodeBounds = false;        return BitmapFactory.decodeResource(res, resId, options);    }

2,从文件流中加载图片。

    /**     * 不能直接对文件流做如下操作,因为两次的decodeStream会影响文件的位置属性     * 导致第二次decodeStream的返回为null,所以中转一下     * FileDescriptor fileDescriptor = FileInputStream.getFD();     */    public Bitmap decodeSampledBitmapFromFileDescriptor(FileDescriptor descriptor, int reqWidth, int reqHeight) {        final BitmapFactory.Options options = new BitmapFactory.Options();        //从文件信息中提取高宽信息        options.inJustDecodeBounds = true;        BitmapFactory.decodeFileDescriptor(descriptor, null, options);        //计算inSampleSize        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);        //正式加载Bitmap        options.inJustDecodeBounds = false;        return BitmapFactory.decodeFileDescriptor(descriptor, null, options);    }

3,计算inSampleSize。

    public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {        if (reqWidth == 0 || reqHeight == 0) {            return 1;        }        final int width = options.outWidth;        final int height = options.outHeight;        Log.i(tag, "outOption: height:" + height + ",widht:" + width);        int inSampleSize = 1;        if (width > reqWidth && height > reqHeight) {            int halfWith = options.outWidth / 2;            int halfHeight = options.outHeight / 2;            while (halfWith / inSampleSize >= reqWidth && halfHeight / inSampleSize >= reqHeight) {                inSampleSize *= 2;            }        }        Log.i(tag, "sampleSize:" + inSampleSize);        return inSampleSize;    }

二,图片的缓存策越

1,读取内存缓存

    private Bitmap loadBitmapFromMemoryCache(String url) {        String key = hashKeyFromUrl(url);//有个加密算法        return getBitmapFromMemoryCache(key);    }
2,读取本地缓存

    /**     * 从磁盘中读取Bitmap,并将其添加到内存缓存     *     */    private Bitmap loadBitmapFromDiskLruCache(String url, int reqWidth, int reqHeight)            throws IOException {        Log.w(tag, "loadBitmapFromDiskLruCache");        if (Looper.myLooper() == Looper.getMainLooper()) {            Log.w(tag, "load bitmap from ui thread, it is not recommended");        }        if (mDiskLruCache == null) {            return null;        }        Bitmap bitmap = null;        String key = hashKeyFromUrl(url);        DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);        if (snapshot != null) {            FileInputStream inputStream = (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX);            FileDescriptor descriptor = inputStream.getFD();            bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptor(descriptor, reqWidth, reqHeight);            if (bitmap != null) {                addBitmapToMemoryCache(key, bitmap);            }        }        return bitmap;    }

3,读取网络资源

    /**     * 读取网络资源并将它写入磁盘缓存     */    private Bitmap loadBitmapFromHttp(String url, int reqWidth, int reqHeight) throws IOException {        if (Looper.myLooper() == Looper.getMainLooper()) {            throw new RuntimeException("can not visit network from ui thread");        }        if (mDiskLruCache == null) {            return null;        }        String key = hashKeyFromUrl(url);        DiskLruCache.Editor editor = mDiskLruCache.edit(key);        if (editor != null) {            OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);            if (downloadUrlToStream(url, outputStream)) {                editor.commit();            } else {                editor.abort();            }            mDiskLruCache.flush();        }        return loadBitmapFromDiskLruCache(url, reqWidth, reqHeight);    }


验证demo





0 0
原创粉丝点击