图片三级缓存的处理 代码实现

参考链接

https://blog.csdn.net/nzfxx/article/details/51818183

图片的工具类

public class MyImageTool {
    private static MyImageTool myImageTool = new MyImageTool();
    //改用缓存集合
    private static LruCache mMCeche;

    private MyImageTool() {
        //这个是定义大小
        //int maxSize = 1024*1024*4;
        //注意这个地方及其的容易出错,因为我写成了freeMemory()/4+0.5f,导致大半天都集合都无法存入东西,因为两者不一样大了,而用int maxSize = 1024*1024*4;里面出现效果
        int maxSize = (int) (Runtime.getRuntime().totalMemory());//四舍五入,用总内存就没错

        mMCeche = new LruCache(maxSize) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                //这个是对应上面的byte,注意单位对应,如果这里想作为M那么上面就写4,这里就写/1024/1024
                return value.getByteCount();
            }
        };
    }

    //1.上下文
    static Context mContext;

    public static MyImageTool with(Context context) {
        mContext = context;
        return myImageTool;
    }

    //2.路径
    public RequestCreator load(String path) {
        RequestCreator creator = new RequestCreator(path);
        return creator;
    }

    Handler mHandler = new Handler();

    public class RequestCreator {
        String mUrl = null;
        ImageView mIv;

        RequestCreator(String path) {
            mUrl = path;
        }

        //3.控件
        public void into(ImageView iv) {
            mIv = iv;
            load();
        }

        private void load() {
            /*-从内存里读取图片    HashMap-*/
            if (loadFromCache()) return;

            /*--从磁盘读取"文件"存入磁盘的是文件file-MD5统一名字,在内存中才是图片bitmap-用url当做名字就行,所以从磁盘读取需要转换成图片;--*/
            if (loadFromDisk()) return;

            /*--从网络获取,开启线程,然后子线程显示即可,再存磁盘,存内存--*/
            loadFromNet();
        }

        //从内存读取
        private boolean loadFromCache() {
            Bitmap bitmapCeche = mMCeche.get(mUrl);
            if (bitmapCeche != null) {
                Log.d("RequestCreator", "显示的是内存的图");
                mIv.setImageBitmap(bitmapCeche);
                return true;
            }
            return false;
        }

        //从磁盘获取
        private boolean loadFromDisk() {

            File file = getFileName();
            try {
                if (file.exists()) {
                    Bitmap bitmapDisk = BitmapFactory.decodeStream(new FileInputStream(file));
                    if (bitmapDisk != null) {
                        Log.d("RequestCreator", "显示的是磁盘的图");
                        mIv.setImageBitmap(bitmapDisk);
                        //立马且存到内存
                        saveCeche(bitmapDisk);
                        return true;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }

        //从网络获取,并存如磁盘和内存
        private void loadFromNet() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        HttpURLConnection conn = (HttpURLConnection) new URL(mUrl).openConnection();
                        conn.setConnectTimeout(4 * 1000);
                        conn.setReadTimeout(4 * 1000);

                        InputStream is = conn.getInputStream();
                        final Bitmap bitmap = BitmapFactory.decodeStream(is);
                        if (bitmap == null) {
                            //没有就显示错误图片
                            showErrorPic();
                            return;
                        }
                        //子线程->主线程显示
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                Log.d("RequestCreator", "显示的是网络的图");
                                mIv.setImageBitmap(bitmap);
                            }
                        });
                        //存到磁盘是file格式,所以内部要处理
                        saveDisk(bitmap);
                        //存到内存的是纯bitmap格式.
                        saveCeche(bitmap);
                        conn.disconnect();
                        is.close();
                    } catch (IOException e) {
                        //异常显示错误图片
                        showErrorPic();
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        //磁盘里的file文件名字
        @NonNull
        private File getFileName() {
            String packageName = mContext.getPackageName();
            File dir = new File("data/data/" + packageName + "/" + "myimage/");//自定义的
            if (!dir.exists()) {
                dir.mkdir();//没有就创建
            }
            String name = MD5Util.getMD5Str(mUrl);
            return new File(dir, name);
        }

        //图片存到磁盘
        private void saveDisk(Bitmap bitmap) {
            File fileName = getFileName();
            //bitmap->file,图片转成文件
            try {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(fileName));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        //图片存到内存的方法
        private void saveCeche(Bitmap bitmap) {
            mMCeche.put(mUrl, bitmap);
            System.out.println("putSize---------------------------------------" + mMCeche.size());
        }

        //显示错误图片
        private void showErrorPic() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    Bitmap error = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_launcher);
                    Toast.makeText(mContext, "Error", Toast.LENGTH_SHORT).show();
                    mIv.setImageBitmap(error);
                }
            });
        }
    }
}

activity中的代码

public class MainActivity extends AppCompatActivity {
    ImageView img;
    String imgURl = "http://cdn.lizhi.fm/radio_cover/2014/08/01/13399312812359682.jpg";

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

        img = (ImageView) findViewById(R.id.img);

        //使用框架
//        Picasso.with(MainActivity.this).load(imgURl).into(mIv);
//        UseTimeTool.getInstance().start();
        //我们自己做的: 上下文->路径->控件
        MyImageTool.with(MainActivity.this).load(imgURl).into(img);
//        UseTimeTool.getInstance().stop();
    }
}

MD5工具类

public class MD5Util {

    public final static String getMD5Str(String pwd) {
        //用于加密的字符
        char md5String[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'A', 'B', 'C', 'D', 'E', 'F'};
        try {
            //使用平台的默认字符集将此 String 编码为 byte序列,并将结果存储到一个新的 byte数组中
            byte[] btInput = pwd.getBytes();

            //信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。
            MessageDigest mdInst = MessageDigest.getInstance("MD5");

            //MessageDigest对象通过使用 update方法处理数据, 使用指定的byte数组更新摘要
            mdInst.update(btInput);

            // 摘要更新之后,通过调用digest()执行哈希计算,获得密文
            byte[] md = mdInst.digest();

            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {   //  i = 0
                byte byte0 = md[i];  //95
                str[k++] = md5String[byte0 >>> 4 & 0xf];    //    5
                str[k++] = md5String[byte0 & 0xf];   //   F
            }

            //返回经过加密后的字符串
            return new String(str);

        } catch (Exception e) {
            return null;
        }
    }
}




你可能感兴趣的:(图片三级缓存的处理 代码实现)