android125 zhihuibeijing 缓存

简介:

 

复制代码
package com.itheima.zhbj52.utils.bitmap;

import android.graphics.Bitmap;
import android.widget.ImageView;

import com.itheima.zhbj52.R;

/**
 * 自定义图片加载工具(源码仿写。实际开发还是要用BitmapUtils,因为图片的缓存比较难)
 */
public class MyBitmapUtils {

    NetCacheUtils mNetCacheUtils;
    LocalCacheUtils mLocalCacheUtils;
    MemoryCacheUtils mMemoryCacheUtils;

    public MyBitmapUtils() {
        mMemoryCacheUtils = new MemoryCacheUtils();
        mLocalCacheUtils = new LocalCacheUtils();
        mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, mMemoryCacheUtils);
    }

    //优先加载内存缓存,然后本地缓存,然后网络缓存。
    public void display(ImageView ivPic, String url) {//加载图片
        ivPic.setImageResource(R.drawable.news_pic_default);// 设置默认加载图片

        Bitmap bitmap = null;
        // 从内存读
        bitmap = mMemoryCacheUtils.getBitmapFromMemory(url);
        if (bitmap != null) {
            ivPic.setImageBitmap(bitmap);
            System.out.println("从内存读取图片啦...");
            return;
        }

        // 从本地读
        bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
        if (bitmap != null) {
            ivPic.setImageBitmap(bitmap);
            System.out.println("从本地读取图片啦...");
            mMemoryCacheUtils.setBitmapToMemory(url, bitmap);// 将图片保存在内存
            return;
        }

        // 从网络读
        mNetCacheUtils.getBitmapFromNet(ivPic, url);
    }

}
复制代码
复制代码
package com.itheima.zhbj52.utils.bitmap;

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

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

/**
 * 网络缓存
 */
public class NetCacheUtils {
    private LocalCacheUtils mLocalCacheUtils;
    private MemoryCacheUtils mMemoryCacheUtils;

    public NetCacheUtils(LocalCacheUtils localCacheUtils,MemoryCacheUtils memoryCacheUtils) {
        mLocalCacheUtils = localCacheUtils;
        mMemoryCacheUtils = memoryCacheUtils;
    }

    /**
     * 从网络下载图片
     */
    public void getBitmapFromNet(ImageView ivPic, String url) {
        new BitmapTask().execute(ivPic, url);// 启动AsyncTask,执行doInBackground,参数会在doInbackground中获取
    }

    /**
     * AsyncTask是对Handler和线程池(很多线程可以同时运行)的封装,Handler里面的方法是在主线程中执行。
     * 
     * 第一个泛型: 参数类型 ,第二个泛型: 更新进度的泛型, 第三个泛型是onPostExecute的返回结果
     */
    class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
        private ImageView ivPic;
        private String url;
        /**
         * 后台耗时方法在此执行, 子线程中执行
         */
        @Override
        protected Bitmap doInBackground(Object... params) {
            ivPic = (ImageView) params[0];
            url = (String) params[1];
            ivPic.setTag(url);// 将url和imageview绑定
            return downloadBitmap(url);//下载图片要在子线程执行,下载完后执行onPostExecute方法,返回的bitmap传给result。
        }

        /**
         * 更新进度, 主线程中执行
         */
        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }

        /**
         * 耗时方法结束后,执行该方法, 主线程中执行
         */
        @Override
        protected void onPostExecute(Bitmap result) {//result是结果,返回的是下载的图片bitmap
            if (result != null) {
                String bindUrl = (String) ivPic.getTag();

                if (url.equals(bindUrl)) {// 前面ivPic.setTag(url),这里是确保图片设定给了正确的imageview防止图片错乱。
                    ivPic.setImageBitmap(result);
                    mLocalCacheUtils.setBitmapToLocal(url, result);// 将图片保存在本地
                    mMemoryCacheUtils.setBitmapToMemory(url, result);// 将图片保存在内存
                    System.out.println("从网络缓存读取图片啦...");
                }
            }
        }
    }

    /**
     * 下载图片
     */
    private Bitmap downloadBitmap(String url) {
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestMethod("GET");
            conn.connect();
            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                InputStream inputStream = conn.getInputStream();
                
                //图片压缩处理()
                BitmapFactory.Options option = new BitmapFactory.Options();
                option.inSampleSize = 2;//宽高都压缩为原来的二分之一, 则图片会失真,此参数需要根据图片要展示的大小来确定。
                option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片格式
                
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.disconnect();
        }
        return null;
    }
}
复制代码
复制代码
package com.itheima.zhbj52.utils.bitmap;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.MessageDigest;

import com.itheima.zhbj52.utils.MD5Encoder;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;

/**
 * 本地缓存sd卡
 */
public class LocalCacheUtils {

    public static final String CACHE_PATH = Environment
            .getExternalStorageDirectory().getAbsolutePath() + "/zhbj_cache_52";//根目录下建一个zhbj_cache_52文件夹。

    /**
     * 从本地sdcard读图片
     */
    public Bitmap getBitmapFromLocal(String url) {
        try {
            String fileName = MD5Encoder.encode(url);
            /*public class MD5Encoder {
                public static String encode(String string) throws Exception {
                    byte[] hash = MessageDigest.getInstance("MD5").digest(
                            string.getBytes("UTF-8"));
                    StringBuilder hex = new StringBuilder(hash.length * 2);
                    for (byte b : hash) {
                        if ((b & 0xFF) < 0x10) {
                            hex.append("0");
                        }
                        hex.append(Integer.toHexString(b & 0xFF));
                    }
                    return hex.toString();
                }
            }*/
            File file = new File(CACHE_PATH, fileName);

            if (file.exists()) {
                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
                        file));//从文件读取图片。
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 向sdcard写图片
     */
    public void setBitmapToLocal(String url, Bitmap bitmap) {
        try {
            String fileName = MD5Encoder.encode(url);//url的MD5为文件名,
            File file = new File(CACHE_PATH, fileName);

            File parentFile = file.getParentFile();//父文件夹
            if (!parentFile.exists()) {// 如果文件夹不存在, 创建文件夹
                parentFile.mkdirs();
            }
            // 将图片保存在本地
            bitmap.compress(CompressFormat.JPEG, 100,
                    new FileOutputStream(file));//CompressFormat.JPEG是压缩格式,100是压缩本质,100%,FileOutputStream是输出流。
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码
复制代码
package com.itheima.zhbj52.utils.bitmap;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;


/*## 内存溢出OOM ##
- Android默认给每个app只分配16M的内存
- java中的引用
    - 强引用 垃圾回收器不会回收, java默认引用都是强引用
    - 软引用 SoftReference   在内存不够时,垃圾回收器会考虑回收(即使这个对象有引用存在也会回收)
    - 弱引用 WeakReference  在内存不够时,垃圾回收器会优先回收
    - 虚引用 PhantomReference  在内存不够时,垃圾回收器最优先回收(不建议使用,因为太容易被回收)

注意: Android2.3+, 系统会优先将SoftReference的对象提前回收掉, 即使内存够用,所以弱引用太容易被回收而不再可靠。

## LruCache(谷歌推荐使用的方法) ##
    least recentlly use 最少最近使用算法
    会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定.

## 图片压缩,否则程序很容易崩溃 ##*/
/**
 * 内存缓存
 */
public class MemoryCacheUtils {

    //private HashMap<String,Bitmap> mMemoryCache = new HashMap<String,Bitmap>();
    // private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new HashMap<String, SoftReference<Bitmap>>();//这里使用弱引用是为了防止内存溢出,弱引用太容易被回收而不再可靠。
    private LruCache<String, Bitmap> mMemoryCache;//LruCache跟HashMap相似采用key,value格式。

    public MemoryCacheUtils() {
        long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 模拟器默认是16M,maxMemory=2M,
        mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
            @Override
            protected int sizeOf(String key, Bitmap value) {//一个Bitmap对象占用的大小。
                //图片显示多大就占用多大内存,图片放大时占用内存大图片缩小时占用内存小。
                //图片占用内存的大小与图片占用的像素点是相关的,图片显示在屏幕上的时候与图片文件的大小无关只与图片占用的像素点多少有关。
                int byteCount = value.getRowBytes() * value.getHeight();// 获取图片占用内存大小,高度*每一行占用的内存大小
                return byteCount;
            }
        };
    }

    /**
     * 从内存读
     */
    public Bitmap getBitmapFromMemory(String url) {
        /*SoftReference<Bitmap> softReference = mMemoryCache.get(url);
             if (softReference != null) {
             Bitmap bitmap = softReference.get();//获取Bitmap对象
             return bitmap;
         }*/
        return mMemoryCache.get(url);
    }

    /**
     * 写内存
     */
    public void setBitmapToMemory(String url, Bitmap bitmap) {
        // SoftReference<Bitmap> softReference = new SoftReference<Bitmap>(bitmap);
        // mMemoryCache.put(url, softReference);
        mMemoryCache.put(url, bitmap);//底层会判断是否超过最大值,超过了就remove第一个。
    }
}
复制代码

 


本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/5071203.html,如需转载请自行联系原作者

相关文章
|
缓存 Android开发
Android Studio中如何清理gradle缓存
Android Studio中如何清理gradle缓存
|
缓存 Android开发
Android - 手机下载的缓存视频在文件管理怎么找不到?
Android - 手机下载的缓存视频在文件管理怎么找不到?
1211 0
Android - 手机下载的缓存视频在文件管理怎么找不到?
|
4月前
|
XML 缓存 Java
Android App开发之利用Glide实现图片的三级缓存Cache讲解及实战(附源码 超详细必看 简单易懂)
Android App开发之利用Glide实现图片的三级缓存Cache讲解及实战(附源码 超详细必看 简单易懂)
118 0
|
12月前
|
缓存 Java Android开发
Android C++ 系列:JNI 调用时缓存字段和方法 ID
通常我们通过 FindClass 、GetFieldID、GetMethodID 去找到对应的信息也是耗时操作,如果方法被频繁调用(特别是像音视频处理时循环的调用JNI方法传递音视频数据),每次都去查找对应的类和方法ID会很耗性能,所以我们必须将它们缓存起来,达到只创建一次,后面直接使用缓存内容的效果。
93 0
|
缓存 Java Android开发
Android使用LruCache、DiskLruCache实现图片缓存+图片瀑布流
**本文仅用于学习利用LruCache、DiskLruCache图片缓存策略、实现瀑布流和Matix查看大图缩放移动等功能,如果想用到项目中,建议用更成熟的框架,如[glide]
130 0
|
存储 缓存 Java
Android使用磁盘缓存DiskLruCache
不同于LruCache,LruCache是将数据缓存到内存中去,而DiskLruCache是外部缓存,例如可以将网络下载的图片永久的缓存到手机外部存储中去,并可以将缓存数据取出来使用,DiskLruCache不是google官方所写,但是得到了官方推荐
143 0
|
存储 缓存 算法
Android内存缓存LruCache源码解析
内存缓存,使用强引用方式缓存有限个数据,当缓存的某个数据被访问时,它就会被移动到队列的头部,当一个新数据要添加到LruCache而此时缓存大小要满时,队尾的数据就有可能会被垃圾回收器(GC)回收掉,LruCache使用的LRU(Least Recently Used)算法,即:<strong>把最近最少使用的数据从队列中移除,把内存分配给最新进入的数据。</strong>
|
存储 缓存 程序员
android DiskCacheDir 硬盘缓存
android DiskCacheDir 硬盘缓存
android DiskCacheDir 硬盘缓存
|
存储 消息中间件 缓存
【Android】开发Android应用时对于Handler消息传递与缓存问题深入运用and理解
【Android】开发Android应用时对于Handler消息传递与缓存问题深入运用and理解
172 0
|
缓存 JSON Java
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录
338 1
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录