Android 高仿ImageLoader图片加载

一、首先,废话不多说,先上图片


二、实现思路

   1、缓存在本地和内存中,每次加载都从本地中读取,如果本地没有则从网络下载,并保存到本地或者内存

   2、内存缓存使用软引用和LruCache算法

  3、本地缓存使用DiskLruCache算法

  4、LruCache算法系统自带,DiskLruCache算法如果没有可以去网上下载,当然最后我会在我的资源里放上源码

三、实现

    1、创建文件目录


2、先创建图片缓存接口 BitmapCache且实现该接口

public interface BitmapCache {
    /**
     * 缓存bitmap
     * @param request
     * @param bitmap
     */
    void put(BitmapRequest request, Bitmap bitmap);

    /**
     * 通过请求去bitmap
     * @param request
     * @return
     */
    Bitmap get(BitmapRequest request);

    /**
     * 移除bitmap
     * @param request
     */
    void remove(BitmapRequest request);
}
本地缓存实现 DiskCache.java
public class DiskCache implements BitmapCache {
    private static DiskCache mDiskCache;
    //缓存路径 ,这里可以换成你想要保存的名字和路径
    private String mCacheDir = "testImage";
    //MB
    private static final int MB = 1024 * 1024;

    private DiskLruCache mDiskLruCache;

    public DiskCache(Context context) {
        initDiskCache(context);
    }

    public static DiskCache getInstance(Context context) {
        if (mDiskCache == null) {
            synchronized (DiskCache.class) {
                if (mDiskCache == null) {
                    mDiskCache = new DiskCache(context);
                }
            }
        }
        return mDiskCache;
    }

    private void initDiskCache(Context context) {
        //得到缓存的目录 data/data目录下,好处,app卸载后,文件自动被删除
        File directory = getDiskCacheDir(mCacheDir, context);
        if (!directory.exists()) {
            directory.mkdirs();
        }

        try {
            //mxSize 指定缓存容量
            mDiskLruCache = DiskLruCache.open(directory, 1, 1, 50 * MB);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private File getDiskCacheDir(String mCacheDir, Context context) {
        File cacheDir = context.getCacheDir();
        File newCacheDir = new File(cacheDir, mCacheDir);
        Log.i("wxf", "new cache path:" + newCacheDir.getAbsolutePath());

        return newCacheDir;
    }

    @Override
    public void put(BitmapRequest request, Bitmap bitmap) {
        DiskLruCache.Editor editor = null;
        OutputStream os = null;
        try {
            //路径必须是合法字符
            editor = mDiskLruCache.edit(request.getImageUriMD5());
            os = editor.newOutputStream(0);
            if (os != null) {
                if (persistBitmap2Disk(bitmap, os)) {
                    editor.commit();
                } else {
                    editor.abort();
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean persistBitmap2Disk(Bitmap bitmap, OutputStream os) {
//图片质量压缩
        BufferedOutputStream bos = new BufferedOutputStream(os);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);

        try {
            bos.flush();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            IOUtil.closeQuietly(bos);
        }

        return true;
    }

    @Override
    public Bitmap get(BitmapRequest request) {
        try {
            DiskLruCache.Snapshot snapshot = mDiskLruCache.get(request.getImageUriMD5());
            if (snapshot != null) {
                InputStream inputStream = snapshot.getInputStream(0);
                return BitmapFactory.decodeStream(inputStream);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void remove(BitmapRequest request) {
        try {
            mDiskLruCache.remove(request.getImageUriMD5());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
内存缓存实现 MemoryCache.java
public class MemoryCache implements BitmapCache {

    private LruCache<String, Bitmap> mLruCache;

    public MemoryCache() {
        int maxSize = (int) (Runtime.getRuntime().freeMemory() / 1024 / 8);
        mLruCache = new LruCache<String, Bitmap>(maxSize) {
            @Override
            protected int sizeOf(String key, Bitmap value) {

                return value.getRowBytes() * value.getHeight();
            }
        };
    }

    @Override
    public void put(BitmapRequest request, Bitmap bitmap) {
        mLruCache.put(request.getImageUriMD5(), bitmap);
    }

    @Override
    public Bitmap get(BitmapRequest request) {
        return mLruCache.get(request.getImageUriMD5());
    }

    @Override
    public void remove(BitmapRequest request) {
        mLruCache.remove(request.getImageUriMD5());
    }
}

缓存调用 DoubleCache.java

public class DoubleCache implements BitmapCache {
    //内存缓存
    private MemoryCache mMemoryCache = new MemoryCache();
    // 硬盘缓存
    private DiskCache mDiskCache;

    public DoubleCache(Context context) {
        mDiskCache = DiskCache.getInstance(context);
    }

    @Override
    public void put(BitmapRequest request, Bitmap bitmap) {
        mMemoryCache.put(request, bitmap);
        mDiskCache.put(request, bitmap);
    }

    @Override
    public Bitmap get(BitmapRequest request) {
        Bitmap bitmap = mMemoryCache.get(request);
        if (bitmap == null) {
            bitmap = mDiskCache.get(request);
            if (bitmap != null) {
                //放入内存,方便获取
                mMemoryCache.put(request, bitmap);
            }
        }
        return bitmap;
    }

    @Override
    public void remove(BitmapRequest request) {
        mMemoryCache.remove(request);
        mDiskCache.remove(request);
    }
}

3、设置加载中和加载失败的默认图片 Displayconfig.java

public class Displayconfig {
    /**
     * 加载过程中默认显示的图片Id
     */
    public int loadingImage = -1;
    /**
     * 加载失败显示的图片
     */
    public int failImage = -1;

}

4、图片加载配置  ImageLoaderConfig.java

public class ImageLoaderConfig {
    //缓存策略
    private BitmapCache bitmapCache=new MemoryCache();

    //加载策略
    private LoadPolicy loadPolicy=new ReversePolicy();
    //默认加载线程数
    private int threadcount = Runtime.getRuntime().availableProcessors();
    //显示配置

    private Displayconfig displayconfig=new Displayconfig();

    private ImageLoaderConfig() {

    }

    /**
     * 建造者模式
     */
    public static class Builder {
        private ImageLoaderConfig config;

        public Builder() {
            this.config = new ImageLoaderConfig();
        }

        /**
         * 设置缓存策略
         *
         * @param bitmapCache
         * @return
         */
        public Builder setCachePlicy(BitmapCache bitmapCache) {
            this.config.bitmapCache = bitmapCache;

            return this;
        }

        /**
         * 设置加载策略
         *
         * @param loadpolicy
         * @return
         */
        public Builder setLoadpolicy(LoadPolicy loadpolicy) {
            this.config.loadPolicy = loadpolicy;
            return this;
        }

        /**
         * 设置线程数量
         *
         * @param threadCount
         * @return
         */
        public Builder setThreadCount(int threadCount) {
            this.config.threadcount = threadCount;
            return this;
        }

        /***
         * 设置加载过程中的图片
         * @param ResID
         * @return
         */
        public Builder setLoadingImage(int ResID) {
            this.config.displayconfig.loadingImage = ResID;
            return this;
        }

        /**
         * 设置加载失败的图片
         *
         * @param ResID
         * @return
         */
        public Builder setFailImage(int ResID) {
            this.config.displayconfig.failImage = ResID;
            return this;
        }


        public ImageLoaderConfig build(){

            return this.config;
        }




    }

    public BitmapCache getBitmapCache() {
        return bitmapCache;
    }

    public LoadPolicy getLoadPolicy() {
        return loadPolicy;
    }

    public int getThreadcount() {
        return threadcount;
    }

    public Displayconfig getDisplayconfig() {
        return displayconfig;
    }
}

5、创建加载接口  Loader.java

public interface Loader {
    /**
     * 加载图片
     *
     * @param request
     */
    void loadImage(BitmapRequest request);
}

实现图片的加载类以实现控制图片加载 SimpleImageLoader.java

public class SimpleImageLoader {

    /**
     * 配置文件
     */
    private ImageLoaderConfig config;
    /**
     * 请求队列
     */
    private RequestQueue mRequestQueue;

    /**
     * 单例对象
     */
    private static volatile SimpleImageLoader mInstance;

    private SimpleImageLoader() {

    }


    private SimpleImageLoader(ImageLoaderConfig imageLoaderConfig) {
        this.config = imageLoaderConfig;
        mRequestQueue = new RequestQueue(config.getThreadcount());
        //开启队列
        mRequestQueue.start();

    }

    /**
     * 获取单例方法
     *
     * @param config
     * @return
     */
    public static SimpleImageLoader getInstance(ImageLoaderConfig config) {
        if (mInstance == null) {
            synchronized (SimpleImageLoader.class) {
                if (mInstance == null) {
                    mInstance = new SimpleImageLoader(config);
                }
            }
        }

        return mInstance;
    }

    /**
     * 第二次获取单例
     *
     * @return
     */
    public static SimpleImageLoader getInstance() {
        if (mInstance == null) {

            throw new UnsupportedOperationException("没有初始化");
        }

        return mInstance;
    }

    /**
     * @param imageView
     * @param uri       file开头
     */
    public void displayImage(ImageView imageView, String uri) {
        displayImage(imageView, uri, null, null);
    }

    public void displayImage(ImageView imageView, String uri, Displayconfig displayconfig, ImageListener imageListener) {
        //实例化一个请求
        BitmapRequest bitmapRequest = new BitmapRequest(imageView, uri, displayconfig, imageListener);
//        添加到队列里边去
        mRequestQueue.addRequest(bitmapRequest);

    }

    public static interface ImageListener {
        void onComplete(ImageView imageView, Bitmap bitmap, String uri);
    }

    /**
     * 获取到全局配置
     *
     * @return
     */
    public ImageLoaderConfig getConfig() {
        return config;
    }
}

实现Loader加载逻辑 AbstarctLoader.java

public abstract class AbstarctLoader implements Loader {
    //拿到用户自定义配置的缓存策略
    private BitmapCache bitmapCache = SimpleImageLoader.getInstance().getConfig().getBitmapCache();
    //拿到显示配置
    private Displayconfig displayConfig = SimpleImageLoader.getInstance().getConfig().getDisplayconfig();

    @Override
    public void loadImage(BitmapRequest request) {
        //从缓存中取到bitmap
        Bitmap bitmap = bitmapCache.get(request);
        if (bitmap == null) {
            //显示默认加载图片
            showLoadingImage(request);
            //开始真正加载图片
            bitmap = onLoad(request);
            //缓存图片
            cacheBitmap(request, bitmap);
        }

        deliveryToUIThread(request,bitmap);
    }
    /**
     * 交给主线程显示
     * @param request
     * @param bitmap
     */
    protected void deliveryToUIThread(final BitmapRequest request, final Bitmap bitmap) {
        ImageView imageView = request.getImageView();
        if(imageView!=null)
        {
            imageView.post(new Runnable() {
                @Override
                public void run() {
                    updateImageView(request, bitmap);
                }

            });
        }

    }

    private void updateImageView(final BitmapRequest request, final Bitmap bitmap) {
        ImageView imageView = request.getImageView();
        //加载正常  防止图片错位
        if(bitmap != null && imageView.getTag().equals(request.getImageUrl())){
            imageView.setImageBitmap(bitmap);
        }
        //有可能加载失败
        if(bitmap == null && request.getDisplayConfig()!=null&&request.getDisplayConfig().failImage!=-1){
            imageView.setImageResource(displayConfig.failImage);
        }
        //监听
        //回调 给圆角图片  特殊图片进行扩展
        if(request.imageListener != null){
            request.imageListener.onComplete(imageView, bitmap, request.getImageUrl());
        }
    }

    private void cacheBitmap(BitmapRequest request, Bitmap bitmap) {
        if (request != null && bitmap != null) {
            synchronized (AbstarctLoader.class) {
                bitmapCache.put(request, bitmap);
            }
        }
    }

    //抽象加载策略,因为加载网络图片和本地图片有差异
    protected abstract Bitmap onLoad(BitmapRequest request);

    private void showLoadingImage(BitmapRequest request) {
        //指定了,显示配置
        if (hasLoadingPlaceHolder()) {
            final ImageView imageView = request.getImageView();
            if (imageView != null) {
                imageView.post(new Runnable() {
                    @Override
                    public void run() {
                        imageView.setImageResource(displayConfig.loadingImage);
                    }
                });
            }
        }
    }

    protected boolean hasLoadingPlaceHolder() {
        return (displayConfig != null && displayConfig.loadingImage > 0);
    }
}

创建本地加载类  LocalLoader.java

public class LocalLoader extends AbstarctLoader {
    @Override
    protected Bitmap onLoad(BitmapRequest request) {
        //得到本地图片的路径
        final String path = Uri.parse(request.getImageUrl()).getPath();

        File file = new File(path);
        if (!file.exists()) {

            return null;
        }
        BitmapDecoder decoder = new BitmapDecoder() {
            @Override
            protected Bitmap decodeBitmapWithOption(BitmapFactory.Options options) {
                return BitmapFactory.decodeFile(path, options);
            }
        };


        return decoder.decoderBitmap(ImageviewHelper.getImageViewWidth(request.getImageView()),
                ImageviewHelper.getImageViewHeight(request.getImageView()));
    }
}

  实现网络加载逻辑 UrlLoader.java

public class UrlLoader extends AbstarctLoader {
    @Override
    protected Bitmap onLoad(final BitmapRequest request) {
        //先下载  后读取
        downloadImgByUrl(request.getImageUrl(), getCache(request.getImageUriMD5()));


        //解码图片
        BitmapDecoder bitmapDecoder = new BitmapDecoder() {
            @Override
            protected Bitmap decodeBitmapWithOption(BitmapFactory.Options options) {
                //bitmap 对象值为空,因为读取的只是宽高
                return BitmapFactory.decodeFile(getCache(request.getImageUriMD5()).getAbsolutePath(), options);
            }
        };
        return bitmapDecoder.decoderBitmap(ImageviewHelper.getImageViewWidth(request.getImageView()),
                ImageviewHelper.getImageViewHeight(request.getImageView()));


    }


    public static boolean downloadImgByUrl(String urlStr, File file) {
        FileOutputStream fos = null;
        InputStream is = null;
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            is = conn.getInputStream();
            fos = new FileOutputStream(file);
            byte[] buf = new byte[512];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            fos.flush();
            return true;

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
            }

            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
            }
        }

        return false;

    }

    private File getCache(String unipue) {
        File file = new File(Environment.getExternalStorageDirectory(), "ImageLoader");
        if (!file.exists()) {
            file.mkdir();
        }
        return new File(file, unipue);
    }
当然如果你既不是本地的地址,也不是网络地址,就返回空的加载实现  NullLoader.java
public class NullLoader extends AbstarctLoader {

    @Override
    protected Bitmap onLoad(BitmapRequest request) {
        return null;
    }
} 

 创建一个加载管理类,把所有的加载类型管理,然后判断进行分发  LoaderManager.java

public class LoaderManager {
    //缓存所有支持的Loader类型
    private Map<String, Loader> mLoaderMap = new HashMap<>();
    private static LoaderManager mInstance = new LoaderManager();

    public static LoaderManager getInstance() {

        return mInstance;
    }

    private LoaderManager() {
        register("http", new UrlLoader());
        register("https", new UrlLoader());
        register("file", new LocalLoader());
    }

    private void register(String schema, Loader loader) {
        mLoaderMap.put(schema, loader);
    }

    public Loader getLoader(String schema) {
        if (mLoaderMap.containsKey(schema)) {
            return mLoaderMap.get(schema);
        }

        return new NullLoader();

    }
}

6、实现图片请求类  BitmapRequest.java

public class BitmapRequest implements Comparable<BitmapRequest> {

    public BitmapRequest(ImageView imageView, String imageUrl, Displayconfig displayconfig, SimpleImageLoader.ImageListener imageListener) {

        this.imageViewSoft = new SoftReference<>(imageView);
        //设置可见的image的Tag为要下载的图片路径
        imageView.setTag(imageUrl);
        this.imageUrl = imageUrl;
        this.imageListener = imageListener;
        if (displayconfig != null)
            this.displayconfig = displayconfig;

        this.imageUriMD5 = MD5Utils.toMD5(imageUrl);
    }

    public BitmapRequest(ImageView imageView, String imageUrl, SimpleImageLoader.ImageListener imageListener) {

        this.imageViewSoft = new SoftReference<>(imageView);
        //设置可见的image的Tag为要下载的图片路径
        imageView.setTag(imageUrl);
        this.imageUrl = imageUrl;
        this.imageListener = imageListener;
        this.imageUriMD5 = MD5Utils.toMD5(imageUrl);
    }

    private Displayconfig displayconfig;
    //持有ImageView的软应用
    private SoftReference<ImageView> imageViewSoft;
    //图片路径
    private String imageUrl;
    //MD5图片路径
    private String imageUriMD5;
    //下载完成监听
    public SimpleImageLoader.ImageListener imageListener;

    public String getImageUriMD5() {
        return imageUriMD5;
    }

    //加载策略
    private LoadPolicy loadPolicy = SimpleImageLoader.getInstance().getConfig().getLoadPolicy();
    //优先级编号
    private int serialNo;

    public int getSerialNo() {
        return serialNo;
    }

    public ImageView getImageView() {
        return imageViewSoft.get();
    }

    public String getImageUrl() {
        return this.imageUrl;
    }

    public void setSerialNo(int serialNo) {
        this.serialNo = serialNo;
    }

    public Displayconfig getDisplayConfig() {
        return displayconfig;
    }
    public LoadPolicy getLoadPolicy() {
        return loadPolicy;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        BitmapRequest that = (BitmapRequest) o;
        if (serialNo != that.serialNo) return false;

        return loadPolicy != null ? loadPolicy.equals(that.loadPolicy) : that.loadPolicy == null;
    }

    @Override
    public int hashCode() {
        int result = loadPolicy != null ? loadPolicy.hashCode() : 0;

        result = 31 * result + serialNo;

        return result;
    }

    //确定优先级
    @Override
    public int compareTo(BitmapRequest o) {
        return loadPolicy.compareto(o, this);
    }
}

实现请求队列   RequestQueue.java

public class RequestQueue {
    /**
     * 优先级阻塞式队列
     * 多线程共享
     * 生产效率和消费者效率差太远
     * 优先级高的队列先被消费
     * 每一个产品都有编号
     */

    private BlockingQueue<BitmapRequest> mRequestsQueue = new PriorityBlockingQueue<>();

    /**
     * 转发器数量
     */
    private int threadcount;
    //一组转发器
    private RequestDispatcher[] mDispatcher;

    private AtomicInteger i = new AtomicInteger(0);

    public RequestQueue(int threadcount) {
        this.threadcount = threadcount;
    }

    /**
     * 添加请求对象
     *
     * @param request
     */
    public void addRequest(BitmapRequest request) {
        //判断请求队列是否包含请求
        if (!mRequestsQueue.contains(request)) {
            //给请求进行编号
            request.setSerialNo(i.incrementAndGet());
            mRequestsQueue.add(request);
        } else {
            Log.w("", "请求已经存在  编号:" + request.getSerialNo());
        }
    }

    /**
     * 开启请求
     */
    public void start() {
        //先停止,在开启
        stop();
        startDispatchers();


    }

    private void startDispatchers() {
        mDispatcher=new RequestDispatcher[threadcount];
        for (int i=0;i<threadcount;i++){
            RequestDispatcher dispatcher=new RequestDispatcher(mRequestsQueue);
            mDispatcher[i]=dispatcher;
            mDispatcher[i].start();
        }

    }

    /**
     * 停止请求
     */
    public void stop() {

    }


}

实现请求转发 RequestDispatcher.java

public class RequestDispatcher extends Thread { 
    //转发器 --------请求转发线程,不断从请求队列获取请求
    //请求队列
    private BlockingQueue<BitmapRequest> mRequestQueue;

    public RequestDispatcher(BlockingQueue<BitmapRequest> mRequestQueue) {
        this.mRequestQueue = mRequestQueue;
    }


    @Override
    public void run() {
        while (!isInterrupted()) {

            try {
                BitmapRequest request = mRequestQueue.take();
                /**
                 *  处理请求对象
                 */
                Log.i("wxf","imageurl:------->"+request.getImageUrl());
                String schema = pareSchema(request.getImageUrl());
                //获取加载器
                Loader loader = LoaderManager.getInstance().getLoader(schema);

                Log.i("wxf","loader------->"+loader);
                    loader.loadImage(request);


            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    private String pareSchema(String imageUrl) {
        if (imageUrl.contains("://")) {
            return imageUrl.split("://")[0];
        } else {
            Log.i("wxf", "不支持此类型");
        }
        return null;
    }
}

7、实现图片压缩类  BitmapDecoder.java

public abstract class BitmapDecoder {

    /**
     * 压缩图片
     * @param reqWidth
     * @param reqheight
     * @return 得到压缩后的图片
     */
    public Bitmap decoderBitmap(int reqWidth, int reqheight) {
        //初始化Options
        BitmapFactory.Options options = new BitmapFactory.Options();
        //得到宽高信息,设置为true不会读取整张图片到内存
        options.inJustDecodeBounds = true;
        decodeBitmapWithOption(options);
        //计算图片缩放比例
        caculateSapleSizeOptions(options, reqWidth, reqheight);
        return decodeBitmapWithOption(options);
    }

    /**
     * 计算缩放比
     * @param options
     * @param reqWidth
     * @param reqHeight
     */
    private void caculateSapleSizeOptions(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        //计算缩放的比例
        //图片的原始宽高
        int width = options.outWidth;
        int height = options.outHeight;

        int inSampleSize = 1;
        //  reqWidth   ImageView的  宽
        if (width > reqWidth || height > reqHeight) {
            //宽高的缩放比例
            int heightRatio = Math.round((float) height / (float) reqHeight);
            int widthRatio = Math.round((float) width / (float) reqWidth);

            //有的图是长图、有的是宽图
            inSampleSize = Math.max(heightRatio, widthRatio);
        }

        //全景图
        //当inSampleSize为2,图片的宽与高变成原来的1/2
        //options.inSampleSize = 2
        options.inSampleSize = inSampleSize;

        //每个像素2个字节
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        //Bitmap占用内存  true
        options.inJustDecodeBounds = false;
        //当系统内存不足时可以回收Bitmap
        options.inPurgeable = true;
        options.inInputShareable = true;
    }

    protected abstract Bitmap decodeBitmapWithOption(BitmapFactory.Options options);
}

实现ImageView控件宽高获取   ImageviewHelper.java

public class ImageviewHelper {

    private static int DEFAULT_WIDTH = 200;
    private static int DEFAULT_HEIGHT = 200;


    public static int getImageViewWidth(ImageView imageView) {
        if (imageView != null) {
            ViewGroup.LayoutParams params = imageView.getLayoutParams();
            int width = 0;
            if (params != null && params.width != ViewGroup.LayoutParams.WRAP_CONTENT) {
                width = imageView.getWidth();
            }

            if (width <= 0 && params != null) {
                width = params.width;
            }

            if (width <= 0) {
                width = getImageViewFieldValue(imageView, "mMaxWidth");
            }

            return width;
        }

        return DEFAULT_WIDTH;
    }
    public static int getImageViewHeight(ImageView imageView) {
        if (imageView != null) {
            ViewGroup.LayoutParams params = imageView.getLayoutParams();
            int height = 0;
            if (params != null && params.height != ViewGroup.LayoutParams.WRAP_CONTENT) {
                height = imageView.getHeight();
            }

            if (height <= 0 && params != null) {
                height = params.height;
            }

            if (height <= 0) {
                height = getImageViewFieldValue(imageView, "mMaxHeight");
            }

            return height;
        }

        return DEFAULT_HEIGHT;
    }
    private static int getImageViewFieldValue(ImageView imageView, String fieldName) {
        try {
            Field field = ImageView.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            int fieldValue = (int) field.get(imageView);
            if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
                return fieldValue;
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return 0;
    }

}

MD5Utils帮助类

public class MD5Utils {

    private static MessageDigest digest;

    static {
        try {
            digest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            Log.d("wxf", "md5 算法不支持!");
        }
    }

    /**
     * MD5加密
     *
     * @param key
     * @return
     */
    public static String toMD5(String key) {
        if (digest == null) {
            return String.valueOf(key.hashCode());
        }
        //更新字节
        digest.update(key.getBytes());
        //获取最终的摘要  十进制的  12345678/ABCD1245
        return convert2HexString(digest.digest());
    }

    /**
     * 转为16进制字符串
     *
     * @param bytes
     * @return
     */
    private static String convert2HexString(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for (byte b : bytes) {
            //->8->08
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

}

8、调用

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private MyAdapter myAdapter;
    private List<Entity> mList = new ArrayList<>();
    SimpleImageLoader simpleImageLoader;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageLoaderConfig config = new ImageLoaderConfig.Builder()
                .setThreadCount(3)
                .setLoadpolicy(new ReversePolicy())
                .setCachePlicy(new DoubleCache(this))
                .setLoadingImage(R.mipmap.ic_launcher)
                .setFailImage(R.mipmap.ic_launcher).build();
        simpleImageLoader = SimpleImageLoader.getInstance(config);

        for (int i = 0; i < 10; i++) {
            Entity entity = new Entity();
            entity.name = i + "fsfdsdfsafdsfsdf";
            mList.add(entity);
        }

        myAdapter = new MyAdapter(mList);
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

        recyclerView.setLayoutManager(new GridLayoutManager(this, 2));

        recyclerView.setAdapter(myAdapter);
    }


    private class Entity {
        public String url;
        public String name;
    }

    private class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private List<Entity> tempList;

        public MyAdapter(List<Entity> mList) {
            this.tempList = mList;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_newandrecommendlesson, parent, false);
            return new myViewHolder(view);
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            ((myViewHolder) holder).textView.setText("" + tempList.get(position).name);
            simpleImageLoader.displayImage(((myViewHolder) holder).imageView, Images[position]);

        }

        @Override
        public int getItemCount() {
            return tempList.size();
        }
    }

    private class myViewHolder extends RecyclerView.ViewHolder {
        public TextView textView;
        public ImageView imageView;

        public myViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.item_newAndRecommendLesson_textView_title);
            imageView = (ImageView) itemView.findViewById(R.id.item_newAndRecommendLesson_imageView_pic);
        }
    }


    private String[] Images = {
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531129921916&di=13350c1a58f32683cfc90185f776d76f&imgtype=0&src=http%3A%2F%2Fpic-cdn.35pic.com%2F58pic%2F13%2F19%2F82%2F95g58PICtAm_1024.jpg",
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130014832&di=57eec36f70f423eb3818e9cb8f4983c8&imgtype=0&src=http%3A%2F%2Ffa.topitme.com%2Fa%2F15%2F92%2F11216657698a59215ao.jpg",
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130111946&di=55862e85879063bb85b76581b2b1b9dd&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F15%2F40%2F27%2F49B58PICXHQ_1024.jpg",
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130126651&di=c28d13fab05f624522ab151241d6cb7d&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F12%2F29%2F66%2F40G58PIC9bI.jpg",
            "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1220481886,24258781&fm=27&gp=0.jpg",
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130151235&di=31bfcab8733a3cba6b8f3e31efc17b09&imgtype=0&src=http%3A%2F%2Fdepot.nipic.com%2Ffile%2F20160628%2F21447645_11093515769.jpg",
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130198048&di=f9b8f99097970275df3905ea6e919f3b&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F13%2F14%2F93%2F70w58PIChtV_1024.jpg",
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130289265&di=e4cfbb4d53acfd1340180168bf67e23e&imgtype=0&src=http%3A%2F%2Fimg15.3lian.com%2F2015%2Ff2%2F159%2Fd%2F95.jpg",
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130307728&di=1e1daaa961b9723c11d961ff8b017f33&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F86d6277f9e2f07083cebe627e224b899a901f22f.jpg",
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531130316514&di=060abcc3e117b44d3432bed4634c0b81&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2Fcefc1e178a82b901ceb88214788da9773912ef84.jpg"
    };
}

注意:1、图片地址用MD5编码之后可是预防非法字符

          2、别忘了添加读取和网络权限

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

        3、DiskLruCache加载类的实现网上代码很多都是通用的,也可以在我的资源中下载

        4、这个还没有实现图片的取消等,那个应该考虑Activity和Fragment然后根据生命周期去做相应的取消










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值