imageLoader加载模版

MD5工具:

package com.bwie.dongchangqi.tinkertest;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by Administrator on 2018/1/19 0019.
 */

public class Md5Utils {

    /*
    * 1.一个运用基本类的实例
    * MessageDigest 对象开始被初始化。该对象通过使用 update 方法处理数据。
    * 任何时候都可以调用 reset 方法重置摘要。
    * 一旦所有需要更新的数据都已经被更新了,应该调用 digest 方法之一完成哈希计算。
    * 对于给定数量的更新数据,digest 方法只能被调用一次。
    * 在调用 digest 之后,MessageDigest 对象被重新设置成其初始状态。
    */
    public static String md5(String context) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(context.getBytes());//update处理
            byte[] encryContext = md.digest();//调用该方法完成计算

            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < encryContext.length; offset++) {//做相应的转化(十六进制)
                i = encryContext[offset];
                if (i < 0) i += 256;
                if (i < 16) buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            return buf.toString();// 32位的加密
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
    
}
二次采样:

package com.bwie.dongchangqi.tinkertest;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.FileDescriptor;
import java.io.InputStream;

/**
 * Created by Administrator on 2018/1/19 0019.
 */

public class ImageResizer {

    private static final String TAG = "ImageResizer";

    public static Bitmap compressBitmap(FileDescriptor fd, int targetWidth, int targetHeight) {
        Bitmap bitmap = null;
        if (targetWidth == 0 || targetHeight == 0) {
            bitmap = BitmapFactory.decodeFileDescriptor(fd);
            return bitmap;
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        // 一开始的时候只加载图片的宽高信息
        options.inJustDecodeBounds = true;
        // 加载图片,将宽高信息放到option里面
        BitmapFactory.decodeFileDescriptor(fd, null, options);

        // 取出图片的原始宽高信息
        int outWidth = options.outWidth;
        int outHeight = options.outHeight;
        // 对缩放比例进行计算
        int inSampleSize = getResizerRate(outWidth, outHeight, targetWidth, targetHeight);
        // 设置缩放比例
        options.inSampleSize = inSampleSize;
        // 加载图片的具体内容,不再只是加载宽高信息
        options.inJustDecodeBounds = false;
        // 设置图片输出的色彩模式-RGB_565
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        // 对图片按我们计算出的比例进行加载
        bitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
        return bitmap;
    }

    public static Bitmap compressBitmap(InputStream inputStream, int targetWidth, int targetHeight) {
        Bitmap bitmap = null;
        if (targetWidth == 0 || targetHeight == 0) {
            bitmap = BitmapFactory.decodeStream(inputStream);
            return bitmap;
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        // 一开始的时候只加载图片的宽高信息
        options.inJustDecodeBounds = true;
        // 加载图片,将宽高信息放到option里面
        BitmapFactory.decodeStream(inputStream, null, options);

        // 取出图片的原始宽高信息
        int outWidth = options.outWidth;
        int outHeight = options.outHeight;
        // 对缩放比例进行计算
        int inSampleSize = getResizerRate(outWidth, outHeight, targetWidth, targetHeight);
        // 设置缩放比例
        options.inSampleSize = inSampleSize;
        // 加载图片的具体内容,不再只是加载宽高信息
        options.inJustDecodeBounds = false;
        // 设置图片输出的色彩模式-RGB_565
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        // 对图片按我们计算出的比例进行加载
        bitmap = BitmapFactory.decodeStream(inputStream, null, options);
        return bitmap;
    }

    public static Bitmap compressBitmap(String filePath, int targetWidth, int targetHeight) {
        Bitmap bitmap = null;
        if (targetWidth == 0 || targetHeight == 0) {
            bitmap = BitmapFactory.decodeFile(filePath);
            return bitmap;
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        // 一开始的时候只加载图片的宽高信息
        options.inJustDecodeBounds = true;
        // 加载图片,将宽高信息放到option里面
        BitmapFactory.decodeFile(filePath, options);

        // 取出图片的原始宽高信息
        int outWidth = options.outWidth;
        int outHeight = options.outHeight;
        // 对缩放比例进行计算
        int inSampleSize = getResizerRate(outWidth, outHeight, targetWidth, targetHeight);
        // 设置缩放比例
        options.inSampleSize = inSampleSize;
        // 加载图片的具体内容,不再只是加载宽高信息
        options.inJustDecodeBounds = false;
        // 设置图片输出的色彩模式-RGB_565
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        // 对图片按我们计算出的比例进行加载
        bitmap = BitmapFactory.decodeFile(filePath, options);
        return bitmap;
    }

    /**
     * 计算图片的压缩比例
     *
     * @return
     */
    private static int getResizerRate(int outWidth, int outHeight, int targetWidth, int targetHeight) {
        // 谷歌官方推荐,压缩比例应该是2的指数次方
        int inSampleSize = 1;
        // 只要我们的图片宽高还大于目标的宽高,就做除2操作,一直到满足我们的尺寸条件
        while (targetWidth < outWidth / inSampleSize || targetHeight < outHeight / inSampleSize) {
            inSampleSize *= 2;
        }
        return inSampleSize;
    }

}

LruCache类直接用本地文件吧,

ImageLoader三级缓存加载图片:

package com.bwie.dongchangqi.tinkertest;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by WuXirui
 * Create Time: 2018/1/4
 * Description:
 */

public class ImageLoader {
    private static final String TAG = "ImageLoader";

    // 当前app可用内存空间
    private static int MAX_VALUABLE_MEMORY = (int) (Runtime.getRuntime().maxMemory() / 1024);
    // 当前可用内存的1/8作为内存缓存空间
    private static int MAX_MEMORY_SIZE = MAX_VALUABLE_MEMORY / 8;
    // 磁盘缓存空间
    private static int MAX_DISK_SIZE = 50 * 1024 * 1024;
    // 核心线程数
    private static int CORE_THREAD_SIZE = 0;
    // 最大线程数
    private static int MAX_THREAD_SIZE = Integer.MAX_VALUE;
    // 存活时间
    private static long KEEPALIVE_TIME = 60L;
    // 磁盘缓存的索引
    private static int FLAG_DISK_INDEX = 0;
    // 流的buffer    private static int CACHE_BUFFER = 8 * 1024;

    private static final int MESSAGE_RECEIVE_RESULT = 0x123;

    private static volatile ImageLoader instance;
    private Context context;
    private LruCache<String, Bitmap> memoryCache;
    private DiskLruCache diskCache;

    // 磁盘缓存路径
    private File cacheDic;

    // 加载的线程池
    private static ThreadPoolExecutor threadPoolExecutor;

    static {
        threadPoolExecutor = new ThreadPoolExecutor(CORE_THREAD_SIZE,
                MAX_THREAD_SIZE,
                KEEPALIVE_TIME,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>());
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MESSAGE_RECEIVE_RESULT:
                    ResultLoader result = (ResultLoader) msg.obj;
                    ImageView imageView = result.imageView;
                    Bitmap bitmap = result.bitmap;
//                    if (bitmap != null) {
//                        imageView.setImageBitmap(bitmap);
//                    }
                    if (imageView.getTag().equals(result.url)) {
                        if (bitmap != null) {
                            imageView.setImageBitmap(bitmap);
                        }
                    }
                    break;
            }
        }
    };

    private ImageLoader(Context context) {
        this.context = context;

        Log.i(TAG, "ImageLoader: size=" + MAX_MEMORY_SIZE);

        memoryCache = new LruCache<String, Bitmap>(MAX_MEMORY_SIZE) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes() * value.getHeight() / 1024;
            }
        };

        cacheDic = getCacheDic(context);

        try {
            diskCache = DiskLruCache.open(cacheDic, 1, 1, MAX_DISK_SIZE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

    private File getCacheDic(Context context) {
        // 如果SD卡可用,就缓存在SD卡中
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            return context.getExternalCacheDir();
        } else { // SD卡不可用,就存在机身存储中
            return context.getCacheDir();
        }
    }

    public void display(ImageView imageView, String url) {
        display(imageView, url, 0, 0);
    }

    public void display(final ImageView imageView, final String url, final int targetWidth, final int targetHeight) {
        // 防止图片错位,添加标识
        imageView.setTag(url);
        // 判断当前内存中是否有这个缓存了
        Bitmap bitmap = hasBitmapInMemory(url);
        if (bitmap != null) {
            Log.i(TAG, "内存缓存1");
            imageView.setImageBitmap(bitmap);
            return;
        }
        // 内存缓存中没有这个缓存
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "线程加载");

                Bitmap bmp = loadBitmap(imageView, url, targetWidth, targetHeight);
                ResultLoader result = new ResultLoader(imageView, url, bmp);

                Message msg = handler.obtainMessage();
                msg.what = MESSAGE_RECEIVE_RESULT;
                msg.obj = result;
                msg.sendToTarget();
            }
        };
        threadPoolExecutor.execute(runnable);
    }

    /**
     * 加载图片
     *
     * @param url
     */
    private Bitmap loadBitmap(ImageView imageView, String url, int targetWidth, int targetHeight) {
        // 再进行一次内存之中的判断
        Bitmap bitmap = hasBitmapInMemory(url);
        if (bitmap != null) {
            Log.i(TAG, "内存缓存2");
            return bitmap;
        }
        // 如果内存缓存中没有图片,就从磁盘缓存中读取
        bitmap = getBitmapFromDisk(url, targetWidth, targetHeight);
        if (bitmap != null) {
            Log.i(TAG, "磁盘缓存");
            return bitmap;
        }
        // 如果磁盘缓存中没有图片,就从网络获取
        try {
            bitmap = getBitmapFromHttp(url, targetWidth, targetHeight);
            if (bitmap != null) {
                Log.i(TAG, "网络缓存");
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return null;
    }

    /**
     * 从网络中获取图片
     *
     * @param url
     * @return
     */
    private Bitmap getBitmapFromHttp(String url, int targetWidth, int targetHeight) throws Exception {
        // 下载图片完成之后保存到磁盘之中,然后从磁盘缓存中取
        String uniqueKey = getUniqueKey(url);
        Log.i(TAG, "uniqueKey: " + uniqueKey);
        DiskLruCache.Editor edit = diskCache.edit(uniqueKey);
        OutputStream outputStream = edit.newOutputStream(FLAG_DISK_INDEX);
        if (downloadUrlToDiskCache(url, outputStream)) {
            diskCache.flush();
            edit.commit();
            Bitmap bitmap = getBitmapFromDisk(url, targetWidth, targetHeight);
            memoryCache.put(uniqueKey, bitmap);
            return bitmap;
        } else {
            return null;
        }
    }

    /**
     * 下载网络图片并保存到磁盘缓存的输出流
     *
     * @param url
     * @param outputStream
     */
    private boolean downloadUrlToDiskCache(String url, OutputStream outputStream) throws Exception {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        InputStream inputStream = response.body().byteStream();
        BufferedOutputStream bos = new BufferedOutputStream(outputStream);
        BufferedInputStream bis = new BufferedInputStream(inputStream);
        int length = 0;
        byte[] buffer = new byte[CACHE_BUFFER];
        while ((length = bis.read(buffer, 0, buffer.length)) != -1) {
            bos.write(buffer, 0, length);
        }
        bos.flush();
        bos.close();
        bis.close();
        inputStream.close();
        outputStream.close();
        return true;
    }

    /**
     * 从磁盘缓存中取数据
     *
     * @param url
     * @return
     */
    private Bitmap getBitmapFromDisk(String url, int targetWidth, int targetHeight) {
        String uniqueKey = getUniqueKey(url);
        Log.i(TAG, "getBitmapFromDisk: uniqueKey:" + uniqueKey);
        if (!TextUtils.isEmpty(uniqueKey)) {
            try {
                DiskLruCache.Snapshot snapshot = diskCache.get(uniqueKey);
                if (snapshot == null) {
                    return null;
                }
                InputStream inputStream = snapshot.getInputStream(FLAG_DISK_INDEX);
                FileInputStream fis = (FileInputStream) snapshot.getInputStream(FLAG_DISK_INDEX);
                FileDescriptor fd = fis.getFD();
//                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                Bitmap bitmap = ImageResizer.compressBitmap(fd, targetWidth, targetHeight);
                if (bitmap == null) {
                    Log.i(TAG, "bitmap is null ");
                }
                // 写入到内存缓存中
                saveBitmapToMemoryCache(url, bitmap);
                return bitmap;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }

    /**
     * 保存bitmap到内存缓存中
     *
     * @param url
     * @param bitmap
     */
    private void saveBitmapToMemoryCache(String url, Bitmap bitmap) {
        if (hasBitmapInMemory(url) == null && bitmap != null) {
            String uniqueKey = getUniqueKey(url);
            Log.i(TAG, "saveBitmapToMemoryCache: 11111");
            memoryCache.put(uniqueKey, bitmap);
            Log.i(TAG, "saveBitmapToMemoryCache: " + memoryCache.get(uniqueKey));
        }
    }

    /**
     * 查询内存缓存中是否有这个缓存
     *
     * @param url
     * @return
     */
    private Bitmap hasBitmapInMemory(String url) {
        String uniqueKey = getUniqueKey(url);
        if (!TextUtils.isEmpty(uniqueKey)) {
            return memoryCache.get(uniqueKey);
        }
        return null;
    }

    /**
     * 获取url的唯一标示
     *
     * @param text
     * @return
     */
    private String getUniqueKey(String text) {
        return Md5Utils.md5(text);
    }

    private static class ResultLoader {
        private ImageView imageView;
        private String url;
        private Bitmap bitmap;

        public ResultLoader(ImageView imageView, String url, Bitmap bitmap) {
            this.imageView = imageView;
            this.url = url;
            this.bitmap = bitmap;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值