android 图片加载工具

来源:互联网 发布:java 获取根目录路径 编辑:程序博客网 时间:2024/05/22 16:56

实现思路:
根据指定的路径从内存中获取图片, 如果存在,则返回图片.
如果不存在,从硬盘中获取图片,如果存在,则返回图片,并且存入内存缓存中.
如果不存在,则从网络上获取图片,如果获取成功,现将图片二次压缩,
则将图片返回,并且存入到磁盘缓存中.
然后将整个的加载任务,添加到线程池中进行管理.

public class ImageLoader {    private ImageLoader() {    }    private static ImageLoader instance;    public static ImageLoader getInstance(Context ctx) {        if (instance == null) {            synchronized (ImageLoader.class) {                if (instance == null) {                    instance = new ImageLoader(ctx);                }            }        }        return instance;    }    /**     * 内存缓存     */    private LruCache<String, Bitmap> mMemoryCache;    /**     * 磁盘缓存     */    private DiskLruCache mDiskLruCache;    private Context mContext;    // 磁盘内存的大小    public static final long DISK_CACHE_SIZE = 1024 * 1024 * 50; // 10M    public static final long IO_BUFFERED_SIZE = 1024 * 1024 * 8;// 8M    public static final int DISK_CACHE_INDEX = 0;    // 磁盘缓存是否创建成功    private boolean mIsDiskLruCacheCreated = false;    public static final String TAG = "tag";    private static final ThreadFactory mThreadFactory = new ThreadFactory() {        private final AtomicInteger mCount = new AtomicInteger(1);        @Override        public Thread newThread(Runnable r) {            // TODO 自动生成的方法存根            return new Thread(r, "ImageLoader#" + mCount.getAndIncrement());        }    };    private static final int corePoolSize=Runtime.getRuntime().availableProcessors();    private static final int maximumPoolSize=corePoolSize*2+1;    private static final int keepAliveTime=10;    public static final Executor POOL_EXECUTOR = new ThreadPoolExecutor(                            corePoolSize, maximumPoolSize,                             keepAliveTime, TimeUnit.SECONDS,                             new LinkedBlockingDeque<Runnable>(),mThreadFactory);   private  HandlerThread handlerThread=new HandlerThread("handlerThread");   private Handler mHandler=new Handler(handlerThread.getLooper()){    public void handleMessage(android.os.Message msg) {           ImageHolder holder= (ImageHolder) msg.obj;           Bitmap bitmap=holder.bitmap;           ImageView imageView=holder.imageView;           String uri=(String) imageView.getTag(TAG_KEY_URI);           if(uri.equals(holder.uri)){               imageView.setImageBitmap(bitmap);           }else{               Log.v(TAG, "set image bitmap ,but url changed ");           }       };      };    public ImageLoader(Context ctx) {        mContext = ctx.getApplicationContext();        // 内存中最大的容量        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);        int cacheSize = maxMemory / 8;        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {            @Override            protected int sizeOf(String key, Bitmap value) {                return value.getRowBytes() * value.getHeight() / 1024;            }        };        File diskCacheDir = getDiskCacheDir(mContext, "bitmap");        if (diskCacheDir.exists()) {            diskCacheDir.mkdirs();        }        try {            if (getUsableSpace(diskCacheDir) > DISK_CACHE_SIZE) {                mDiskLruCache = DiskLruCache.open(diskCacheDir, 1, 1,                        DISK_CACHE_SIZE);                mIsDiskLruCacheCreated = true;            }        } catch (IOException e) {            e.printStackTrace();            mIsDiskLruCacheCreated = false;        }    }    public static final int TAG_KEY_URI=1;    /**     * 绑定图片与控件   外界调用的方法     * @param url     * @param imageview     * @param reqWidth     * @param reqHeight     */    public void bindBitmap(final String url,final ImageView imageview,final int reqWidth,final int reqHeight){        imageview.setTag(TAG_KEY_URI,url);        Bitmap bitmap=loadBitmapFromMemCache(url);        if(bitmap!=null){            imageview.setImageBitmap(bitmap);            return;        }        Runnable loadTask=new Runnable() {            @Override            public void run() {                Bitmap bitmap=loadBitmap(url,reqWidth,reqHeight);                if(bitmap!=null){                    ImageHolder holder=new ImageHolder(imageview, url, bitmap);                    Message msg=Message.obtain();                    msg.obj=holder;                    mHandler.sendMessage(msg);                }            }        };        POOL_EXECUTOR.execute(loadTask);        }    /**     * 从内存中获取图片     *      * @param key     * @param bitmap     */    public void addBitmapToMemoryCache(String key, Bitmap bitmap) {        if (getBitmapFromMemoryCache(key) != null) {            mMemoryCache.put(key, bitmap);        }    }    public Bitmap loadBitmapFromMemCache(String url) {        String key = hashKeyFromUrl(url);        return getBitmapFromMemoryCache(key);    }    /**     * 将图片存入到缓存     *      * @param key     * @return     */    public Bitmap getBitmapFromMemoryCache(String key) {        return mMemoryCache.get(key);    }    /**     * 从内存缓存,磁盘缓存,网络上读取图片     * @param url     * @param reqWidth     * @param reqHeight     * @return     */    private Bitmap loadBitmap(String url, int reqWidth, int reqHeight) {        Bitmap bitmap = loadBitmapFromMemCache(url);        if (bitmap != null) {            return bitmap;        }        bitmap = loadBitmapFromDiskCache(url, reqWidth, reqHeight);        if (bitmap != null) {            return bitmap;        }        bitmap = loadBitmapFromHttp(url, reqWidth, reqHeight);        if (bitmap == null && !mIsDiskLruCacheCreated) {            bitmap = loadBitmapFromUrl(url);        }        return bitmap;    }    /**     * 从网络上获取图片,将下载的图片存入磁盘缓存中, 然后读取     *      * @param url     * @param reqWidth     * @param reqHeight     * @return     */    private Bitmap loadBitmapFromHttp(String url, int reqWidth, int reqHeight) {        if (Looper.getMainLooper() == Looper.myLooper()) {            throw new RuntimeException(" 不再在主线程中访问网络");        }        if (mDiskLruCache == null) {            return null;        }        String key = hashKeyFromUrl(url);        try {            Editor editor = mDiskLruCache.edit(key);            if (editor != null) {                OutputStream os = editor.newOutputStream(DISK_CACHE_INDEX);                if (downloadUrlToStream(url, os)) {                    editor.commit();                } else {                    editor.abort();                }                mDiskLruCache.flush();            }        } catch (IOException e) {            // TODO 自动生成的 catch 块            e.printStackTrace();        }        return loadBitmapFromDiskCache(url, reqWidth, reqHeight);    }    /**     * 将指定网络路径的文件保存到指定的输入流中     *      * @param url     * @param os     * @return     */    public boolean downloadUrlToStream(String urlString, OutputStream os) {        HttpURLConnection conn = null;        BufferedInputStream bis = null;        BufferedOutputStream bos = null;        try {            URL url = new URL(urlString);            conn = (HttpURLConnection) url.openConnection();            bis = new BufferedInputStream(conn.getInputStream(),                    (int) IO_BUFFERED_SIZE);            bos = new BufferedOutputStream(os);            int len = 0;            byte[] buff = new byte[20];            while ((len = bis.read(buff)) != -1) {                bos.write(buff, 0, len);                bos.flush();            }            return true;        } catch (Exception e) {            e.printStackTrace();        } finally {            if (conn != null) {                conn.disconnect();            }            if (bis != null) {                try {                    bis.close();                } catch (IOException e) {                    // TODO 自动生成的 catch 块                    e.printStackTrace();                }            }            if (bos != null) {                try {                    bos.close();                } catch (IOException e) {                    // TODO 自动生成的 catch 块                    e.printStackTrace();                }            }        }        return false;    }    /**     * 从磁盘上获取图片     *      * 从指定的磁盘路径中获取图片, 如果获取成功,将图片返回, 并且将图片存入内存缓存中     *      * @param url     * @param reqWidth     * @param reqHeight     * @return     */    private Bitmap loadBitmapFromDiskCache(String url, int reqWidth,            int reqHeight) {        if (Looper.myLooper() == Looper.getMainLooper()) {            Log.v(TAG, "load bitmap from UI thread . it's not recommended.");            return null;        }        if (mDiskLruCache == null) {            return null;        }        Bitmap bitmap = null;        String key = hashKeyFromUrl(url);        try {            Snapshot snapshot = mDiskLruCache.get(key);            if (snapshot != null) {                FileInputStream fis = (FileInputStream) snapshot                        .getInputStream(DISK_CACHE_INDEX);                FileDescriptor fds = fis.getFD();                bitmap = BitmapUtils.decodeBitmapFromFileDescriptor(fds,                        reqWidth, reqHeight);                if (bitmap != null) {                    addBitmapToMemoryCache(url, bitmap);                }            }        } catch (IOException e) {            // TODO 自动生成的 catch 块            e.printStackTrace();        }        return bitmap;    }    /**     * 从网络上下载图片     *      * @param urlString     * @return     */    private Bitmap loadBitmapFromUrl(String urlString) {        Bitmap bitmap = null;        HttpURLConnection conn = null;        BufferedInputStream bis = null;        try {            URL url = new URL(urlString);            conn = (HttpURLConnection) url.openConnection();            bis = new BufferedInputStream(conn.getInputStream(),                    (int) IO_BUFFERED_SIZE);            bitmap = BitmapFactory.decodeStream(bis);        } catch (Exception e) {        } finally {            if (bis != null) {                try {                    bis.close();                } catch (IOException e) {                    // TODO 自动生成的 catch 块                    e.printStackTrace();                }            }            if (conn != null) {                conn.disconnect();                conn = null;            }        }        return bitmap;    }    /**     * 将网络路径加密     *      * @param url     * @return     */    private String hashKeyFromUrl(String url) {        String result = null;        try {            MessageDigest mDigest = MessageDigest.getInstance("MD5");            mDigest.update(url.getBytes());            result = byteToHexString(mDigest.digest());        } catch (NoSuchAlgorithmException e) {            result = String.valueOf(url.hashCode());        }        return result;    }    private String byteToHexString(byte[] bytes) {        StringBuffer sb = new StringBuffer();        for (int i = 0; i < bytes.length; i++) {            String hex = Integer.toHexString(0xff & bytes[i]);            if (hex.length() == 1) {                sb.append('0');            }            sb.append(hex);        }        return sb.toString();    }    /**     * 指定磁盘的文件目录     *      * @param ctx     * @param uniqueName     * @return     */    @SuppressLint("NewApi")    public File getDiskCacheDir(Context ctx, String uniqueName) {        String cachePath;        if (Environment.MEDIA_MOUNTED.equals(Environment                .getExternalStorageDirectory())                || !Environment.isExternalStorageRemovable()) {            cachePath = ctx.getExternalCacheDir().getPath();        } else {            cachePath = ctx.getCacheDir().getPath();        }        return new File(cachePath + File.separator + uniqueName);    }    /**     * 获取指定目录的大小     *      * @param path     * @return     */    @SuppressLint("NewApi")    private long getUsableSpace(File path) {        if (Build.VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {            return path.getUsableSpace();        }        StatFs stats = new StatFs(path.getPath());        return stats.getBlockSize() * stats.getAvailableBlocks();    }    private class ImageHolder {        public ImageView imageView;        public String uri;        public Bitmap bitmap;        public ImageHolder(ImageView imageView, String uri, Bitmap bitmap) {            this.imageView = imageView;            this.uri = uri;            this.bitmap = bitmap;        }    }}
0 0
原创粉丝点击