Android加载网络图片的工具类

ImageView加载网络的图片

HttpUtil.java

package com.eiice.httpuimagetils;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.graphics.Bitmap;
import android.util.Log;

/**
 * @author 与网络连接的工具类
 *
 */
public class HttpUtil {

    public static Bitmap download(String path){
        try{
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            InputStream in = conn.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int len = 0;
            byte buff[] = new byte[1024];
            while((len = in.read(buff)) > 0){
                out.write(buff, 0 ,len);
            }
            in.close();
            out.close();
            Log.e("test", "download:"+path);
            byte image[] = out.toByteArray();
            return ImageUtil.bytes2Bimap(image);
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }
}

ImageLoader.java

package com.eiice.httpuimagetils;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.WeakHashMap;

import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.widget.ImageView;

/**
 * 本地图片加载,没有获取到网络的图片数据,就先显示本地的。得到网络的数据,再显示最新的。
 */
public class ImageLoader {

    private static final String TAG = "ImageLoader";

    private ImageCache cache;

    private HashSet<String> cacheKeys = new HashSet<String>();

    private ImageDownloader downloader;

    private WeakHashMap<ImageView, String> imageView2FileMap = new WeakHashMap<ImageView, String>();
    private HashMap<String, HashSet<ImageViewReference>> file2ImageViewMap = new HashMap<String, HashSet<ImageViewReference>>();
    private HashSet<String> fileInLoadSet = new HashSet<String>();

    public ImageLoader(ImageDownloader downloader) {
        if(downloader == null){
            throw new RuntimeException("ImageDownloader can not be null");
        }
        this.cache = ImageCache.getInstance();
        this.downloader = downloader;
    }

    /**
     * @return 缓存中有,直接设置,并返回true,没有异步读取,读完再设置,返回false
     */
    public boolean loadImage(String filePath, int width, int height, ImageView imageView) {
        String filePathKey = getKeyForFilePath(filePath, width, height);
        Bitmap bmp = cache.get(filePathKey);
        if (bmp == null) {
            ImageViewReference imageViewRef = new ImageViewReference(imageView);
            // 更新imageView和filepath的最新的关系
            imageView2FileMap.put(imageView, filePathKey);
            HashSet<ImageViewReference> imageViewSet = file2ImageViewMap.get(filePathKey);
            if (imageViewSet == null) {
                imageViewSet = new HashSet<ImageViewReference>();
                file2ImageViewMap.put(filePathKey, imageViewSet);
            }
            imageViewSet.add(imageViewRef);
            // 防止重复下载
            if (fileInLoadSet.contains(filePathKey)) {
                return false;
            } else {
                fileInLoadSet.add(filePathKey);
            }
            Holder holder = new Holder();
            holder.width = width;
            holder.height = height;
            holder.filePath = filePath;
            holder.filePathKey = filePathKey;
            holder.imageViewRef = imageViewRef;
            new ImageLoadTask().execute(holder);
            return false;
        } else {
            imageView.setImageBitmap(bmp);
            return true;
        }

    }

    private class ImageLoadTask extends AsyncTask<Holder, Void, Holder> {

        @Override
        protected Holder doInBackground(Holder... params) {
            Holder holder = params[0];
            int width = holder.width;
            int height = holder.height;
            String filePath = holder.filePath;
            String filePathKey = holder.filePathKey;
            int count = getCountOfImageViewForKey(filePathKey);
            if (count <= 0) {
                return null;
            }
            try {
                Random rnd = new Random();
                Thread.sleep((int) (1000 * rnd.nextDouble()));
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(downloader != null){
                Bitmap bmp = downloader.download(filePath, width, height);
                if(bmp != null){
                    cache.put(filePathKey, bmp);
                    cacheKeys.add(filePath);
                    holder.imageData = bmp;
                }
            }
            return holder;
        }

        @Override
        protected void onPostExecute(Holder holder) {
            super.onPostExecute(holder);
            String filePathKey = holder.filePathKey;
            fileInLoadSet.remove(filePathKey);

            Bitmap data = holder.imageData;
            if(data == null){
                return;
            }

            ArrayList<ImageView> imageViewArrayList = getImageViewListForKey(filePathKey);
            if (imageViewArrayList.size() == 0) {
                return;
            }
            for (ImageView imageView : imageViewArrayList) {
                String latestFilePathKey = imageView2FileMap.get(imageView);
                if (latestFilePathKey != null && latestFilePathKey.equals(filePathKey)) {
                    if (imageView != null) {
                        imageView.setImageBitmap(data);
                        Log.e(TAG, "设置图片 ");
                        /*
                         * boolean isSet;
                         * try{
                         *         isSet=(Boolean)
                         *         imageView.getTag();
                         * }catch(Exception e) {
                         *         isSet=true;
                         * }
                         * if(isSet) {
                         *         imageView.setImageBitmap(result);
                         *         Log.e(TAG,"设置图片 ");
                         * }
                         */
                    }
                    imageView2FileMap.remove(imageView);
                } else {

                }
            }
            file2ImageViewMap.remove(filePathKey);
        }
    }

    class Holder {
        int width,height;
        String filePath, filePathKey;
        Bitmap imageData;
        ImageViewReference imageViewRef;
    }

    private String getKeyForFilePath(String imagePath, int width, int height) {
        return imagePath + "_" + width + "_" + height;
    }

    /**
     * ????ImageLoader
     *
     * */
    public void clear(){
        imageView2FileMap.clear();
        file2ImageViewMap.clear();
        fileInLoadSet.clear();
        for(String cacheKey : cacheKeys){
            cache.remove(cacheKey);
        }
        cacheKeys.clear();
        imageView2FileMap = null;
        file2ImageViewMap = null;
        fileInLoadSet = null;
        cacheKeys = null;
        downloader = null;
        cache = null;
    }

    /**
     * ImageLoader.java退出时调用
     *
     * */
    public void destory() {
        clear();
        ImageCache.destroy();
    }

    public interface ImageDownloader{
        public Bitmap download(String path,int width, int height);
    }

    /**
     * 通过file2ImageViewMap获取filePath对应的所有imageView列表 同时删除被回收的imageView,
     *
     * @param filePathKey
     * @return
     */
    private ArrayList<ImageView> getImageViewListForKey(String filePathKey) {
        ArrayList<ImageView> imageViewArrayList = new ArrayList<ImageView>();
        HashSet<ImageViewReference> imageViewReferences = file2ImageViewMap.get(filePathKey);
        if(imageViewReferences == null){
            return null;
        }
        Iterator<ImageViewReference> it = imageViewReferences.iterator();
        while (it.hasNext()) {
            ImageViewReference reference = it.next();
            if (reference.get() != null) {
                imageViewArrayList.add(reference.get());
            } else {
                it.remove();
            }
        }
        return imageViewArrayList;
    }

    /**
     * 获取指定的filePath对应的有效imageView的数据
     *
     * @param filePathKey
     * @return
     */
    private int getCountOfImageViewForKey(String filePathKey) {
        ArrayList<ImageView> imageViewArrayList = getImageViewListForKey(filePathKey);
        if(imageViewArrayList == null){
            return 0;
        }else{
            return imageViewArrayList.size();
        }
    }

    private static class ImageCache extends LruCache<String, Bitmap> {
        private static final int cacheSize = 10 * 1024 * 1024;
        private static ImageCache instance = new ImageCache(cacheSize);
        public static ImageCache getInstance(){
            return instance;
        }
        private ImageCache(int maxSize) {
            super(maxSize);
        }
        @Override
        protected int sizeOf(String key, Bitmap value) {
            return value.getByteCount();
        }
        public static void destroy(){
            if(instance == null){
                return;
            }
            instance.evictAll();
            instance = null;
        }
    }

    private static class ImageViewReference extends WeakReference<ImageView> {
        public ImageViewReference(ImageView r) {
            super(r);
        }
        @Override
        public boolean equals(Object o) {
            ImageViewReference other=(ImageViewReference)o;
            return this.get()==other.get();
        }
        @Override
        public int hashCode() {
            ImageView imageView = this.get();
            if(imageView != null){
                return imageView.hashCode();
            }
            return 0;
        }
    }

}

ImageUtil.java

package com.eiice.httpuimagetils;

import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;

public class ImageUtil {

    static final String TAG="ImageUtil";

    public static Bitmap compressPic2Bitmap(String picfullname) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(picfullname, options); // 此时返回bm为空
        options.inJustDecodeBounds = false;
        int be = (int) (options.outHeight / (float) 200);
        if (be <= 0)
            be = 1;
        options.inSampleSize = be;
        bitmap = BitmapFactory.decodeFile(picfullname, options);
        return bitmap;
    }

    public static Drawable bitmap2Drawable(Bitmap bm) {
        BitmapDrawable bd = new BitmapDrawable(bm);
        return bd;
    }

    public static Drawable compressPic2Drawable(String picfullname) {
        return bitmap2Drawable(compressPic2Bitmap(picfullname));
    }

    public static Bitmap compressPic2Bitmap(Bitmap bitmap, int width, int height, boolean isAdjust) {
        if (bitmap.getWidth() < width && bitmap.getHeight() < height) {
            return bitmap;
        }
        float sx = new BigDecimal(width).divide(new BigDecimal(bitmap.getWidth()), 4, BigDecimal.ROUND_DOWN)
                .floatValue();
        float sy = new BigDecimal(height).divide(new BigDecimal(bitmap.getHeight()), 4, BigDecimal.ROUND_DOWN)
                .floatValue();
        if (isAdjust) {
            sx = (sx < sy ? sx : sy);
            sy = sx;
        }
        Matrix matrix = new Matrix();
        matrix.postScale(sx, sy);
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    }

    public static Drawable compressPic2Drawable(String picfullname, int width, int height) {
        // Bitmap bitmap = compressPic2Bitmap(picfullname);
        // bitmap = compressPic2Bitmap(bitmap, width, height, true);

        Bitmap bitmap = compressBitmap(picfullname, width, height);
        return new BitmapDrawable(bitmap);
    }

    public static Bitmap compressBitmap(String path, int sdwidth, int sdheight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        BitmapFactory.decodeFile(path, options);
        options.inSampleSize = calculateSampleSize(options, sdwidth, sdheight);
        options.inJustDecodeBounds = false;
        options.inDither = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        return BitmapFactory.decodeFile(path, options);
    }

    public static int calculateSampleSize(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 = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }
    /**
     * 有损压缩图片
     * @param filePath
     * @return
     */
    public static byte[] compressBitmap(String filePath) {
        Bitmap sourceBmp=BitmapFactory.decodeFile(filePath);
        if(sourceBmp!=null)
        {
            Log.e(TAG, "原大小"+sourceBmp.getByteCount());
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            sourceBmp.compress(Bitmap.CompressFormat.JPEG, 60, baos);
            sourceBmp.recycle();
            sourceBmp=null;
            //如果压缩后还大于10M,再压一次,这种情况一般不会出现
            if(baos.size()>10*1024*1024)
            {
                byte[] bytes=baos.toByteArray();
                Bitmap tempBmp=BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                baos.reset();
                tempBmp.compress(Bitmap.CompressFormat.JPEG, 30, baos);
                tempBmp.recycle();
                tempBmp=null;
            }
            byte[] bytes=baos.toByteArray();
            Log.e(TAG, "压缩后大小"+bytes.length);
            return bytes;
        }else{
            return null;
        }
    }

    public static Bitmap bytes2Bimap(byte[] b) {
         if (b.length != 0) {
             return BitmapFactory.decodeByteArray(b, 0, b.length);
         } else {
             return null;
         }
     }
}

测试代码:activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="400dp"
        android:layout_height="400dp" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="show" />

</LinearLayout>

MainActivity.java

package com.eiice.cn;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

import com.eiice.httpuimagetils.HttpUtil;
import com.eiice.httpuimagetils.ImageLoader;
import com.eiice.httpuimagetils.ImageLoader.ImageDownloader;

public class MainActivity extends Activity {
    private ImageLoader imageLoader;
    private ImageView imageview;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageview = (ImageView) findViewById(R.id.imageview);
        imageLoader = new ImageLoader(new ImageDownloader(){
            @Override
            public Bitmap download(String path, int width, int height) {
                return HttpUtil.download(path);
            }
        });
    }

    public void show(View view){

        String imagepath = "http://img4.duitang.com/uploads/blog/201309/30/20130930115633_h8BEL.thumb.600_0.jpeg";
        imageLoader.loadImage(imagepath , 50, 50, imageview);
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        imageLoader.destory();
    }

}
时间: 2024-10-06 22:05:20

Android加载网络图片的工具类的相关文章

Android加载网络图片报android.os.NetworkOnMainThreadException异常

Android加载网络图片大致可以分为两种,低版本的和高版本的.低版本比如4.0一下或者更低版本的API直接利用Http就能实现了: 1.main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="

Android加载网络图片学习过程

好多应用,像我们公司的<乘友>还有其他的<飞鸽><陌陌><啪啪>这些,几乎每一款应用都需要加载网络图片,那ToYueXinShangWan,这是比须熟练掌握的一个点,下面开始学习: 一.最简单加载网络图片 从网络上取图片数据,显示在应用中,简单不赘述: try { URL url = new URL(path); //path图片的网络地址 HttpURLConnection httpURLConnection = (HttpURLConnection) u

android加载网络图片并保留缓存,随时点击打开

今天工作需要写了一个保留网络图片缓存的类,和大家分享一下 其实实现原理很简单,也就是从网上下载图片数据,一边将数据转成drawable并加载到指定的imageview 一边保存成download_image.jpg,在点击imageview时候用intent将图片打开 我将处理图片的过程写成了类 package com.example.downloadandopenimage; import java.io.File; import java.io.FileOutputStream; impor

Java加载Properties配置文件工具类

import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * Created by yang on 2017/1/5. * 静态配置 */ public class Constants

Android 加载网络图片时 宽度固定 按等比例显示

View v = LayoutInflater.from(TourBuyDetailsActivity.this ).inflate(R.layout.tour_details_header_img_item,null); final ImageView imageView = (ImageView) v.findViewById(R.id.content_pic); ImageLoader.getInstance().displayImage(travelMode.getMedia().ima

Android中用双缓存技术,加载网络图片

最近在学校参加一个比赛,写的一个Android应用,里面要加载大量的网络图片,可是用传统的方法图片一多就会造成程序出现内存溢出而崩溃.因为自己也在学习中,所以看了很多博客和视频,然后参照这些大神的写源码,自己写了一个加载网络图片工具类. 里面要用到一个经典的图片缓存库DiskLruCache 下载地址为:  DiskLruCache下载 下面是使用这个类实现的 双缓存网络图片加载 [java] view plain copy public class DiskLruCacheUtils { pr

Android 异步加载网络图片并缓存到本地

在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片. 软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取. 记得2月份在和爱奇艺公司的项目总监一起搞联通的OTT盒子的时候他就提了一下软引用,奇艺做的手机客户端就是采用这种方法,所以你会发现奇艺客户端占用很大的空间,下面就分享一下异步加载网络图片的方法吧. FileCache

Android Volley入门到精通:使用Volley加载网络图片

在上一篇文章中,我们了解了Volley到底是什么,以及它的基本用法.本篇文章中我们即将学习关于Volley更加高级的用法,如何你还没有看过我的上一篇文章的话,建议先去阅读Android Volley完全解析(一),初识Volley的基本用法. 在上篇文章中有提到过,Volley是将AsyncHttpClient和Universal-Image-Loader的优点集成于一身的一个框架.我们都知道,Universal-Image-Loader具备非常强大的加载网络图片的功能,而使用Volley,我们

Android之ListView异步加载网络图片(优化缓存机制)【转】

网上关于这个方面的文章也不少,基本的思路是线程+缓存来解决.下面提出一些优化: 1.采用线程池 2.内存缓存+文件缓存 3.内存缓存中网上很多是采用SoftReference来防止堆溢出,这儿严格限制只能使用最大JVM内存的1/4 4.对下载的图片进行按比例缩放,以减少内存的消耗 具体的代码里面说明.先放上内存缓存类的代码MemoryCache.java: public class MemoryCache { private static final String TAG = "MemoryCa