SharePreference工具类
  1. /**
    * SharePreference封装
    *
    */
    public class PrefUtils {
    public static final String PREF_NAME = "config";
    public static boolean getBoolean(Context ctx, String key,
    boolean defaultValue) {
    SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
    Context.MODE_PRIVATE);
    return sp.getBoolean(key, defaultValue);
    }
    public static void setBoolean(Context ctx, String key, boolean value) {
    SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
    Context.MODE_PRIVATE);
    sp.edit().putBoolean(key, value).commit();
    }
    public static String getString(Context ctx, String key, String defaultValue) {
    SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
    Context.MODE_PRIVATE);
    return sp.getString(key, defaultValue);
    }
    public static void setString(Context ctx, String key, String value) {
    SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
    Context.MODE_PRIVATE);
    sp.edit().putString(key, value).commit();
    }
    }

缓存工具类

  1. public class CacheUtils {
    /**
    * 缓存原理:设置缓存 key 是url, value是json(解析出来的)
    */
    public static void setCache(String key, String value, Context ctx) {
    PrefUtils.setString(ctx, key, value);
    // 可以将缓存放在文件中, 文件名就是Md5(url), 文件内容是json
    }
    /**
    * 获取缓存 key 是url
    */
    public static String getCache(String key, Context ctx) {
    return PrefUtils.getString(ctx, key, null);
    }
    }
用法:
1.在请求完网络,获取json数据后保存起来
  1. private void getDataFromServer() {
    HttpUtils utils = new HttpUtils();
    utils.send(HttpMethod.GET, GlobalContants.PHOTOS_URL,
    new RequestCallBack<String>() {
    @Override
    public void onSuccess(ResponseInfo<String> responseInfo) {
    String result = (String) responseInfo.result;
    parseData(result);
    // 设置缓存
    CacheUtils.setCache(GlobalContants.PHOTOS_URL, result,
    mActivity);
    }
    @Override
    public void onFailure(HttpException error, String msg) {
    Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT)
    .show();
    error.printStackTrace();
    }
    });
    }
2.在初始化数据的时候判断,可以直接解析数据,也可以什么都不做,然后获取网络数据看有没有最新的
  1. 	public void initData() {
    String cache = CacheUtils
    .getCache(GlobalContants.PHOTOS_URL, mActivity);
    if (!TextUtils.isEmpty(cache)) {
    // parseData(cache);
    }
    getDataFromServer();
    }
解析数据
  1. protected void parseData(String result) {
    Gson gson = new Gson();
    PhotosData data = gson.fromJson(result, PhotosData.class);
    mPhotoList = data.data.news;// 获取组图列表集合
    if (mPhotoList != null) {
    mAdapter = new PhotoAdapter();
    lvPhoto.setAdapter(mAdapter);
    gvPhoto.setAdapter(mAdapter);
    }
    }

三级缓存

- 内存缓存, 优先加载, 速度最快
- 本地缓存, 次优先加载, 速度快
- 网络缓存, 不优先加载, 速度慢,浪费流量
 
服务器端下载的图片是使用 Http的缓存机制,每次执行将本地图片的时间发送给服务器,如果返回码是 304,说明服务端的图片和本地的图片是相同的,直接使用本地保存的图片,如果返回码是 200,则开始下载新的图片并实现缓存。在从服务器获取到图片后,需要再在本地和内存中分别存一份,这样下次直接就可以从内存中直接获取了,这样就加快了显示的速度,提高了用户的体验。
 
内存溢出OOM
导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理

内存溢出(oom) out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak会最终会导致out of memory!

解决方法1:java中的引用(使用软引用)

    - 强引用 垃圾回收器不会回收, java默认引用都是强引用
    - 软引用 SoftReference   在内存不够时,垃圾回收器会考虑回收
    - 弱引用 WeakReference  在内存不够时,垃圾回收器会优先回收
    - 虚引用 PhantomReference  在内存不够时,垃圾回收器最优先回收

注意: Android2.3+, 系统会优先将SoftReference的对象提前回收掉, 即使内存够用

 解决方法2:LruCache 
    least recentlly use 最少最近使用算法

会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定

解决方法3:图片压缩

 
xutils就是这个原理,现在不用xutils,现在自定义几个工具类
 
1.自定义加载工具类
  1. 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);
    }
    }
2.网络缓存、AsyncTask
  1. public class NetCacheUtils {
    private LocalCacheUtils mLocalCacheUtils;
    private MemoryCacheUtils mMemoryCacheUtils;
    public NetCacheUtils(LocalCacheUtils localCacheUtils,
    MemoryCacheUtils memoryCacheUtils) {
    mLocalCacheUtils = localCacheUtils;
    mMemoryCacheUtils = memoryCacheUtils;
    }
    /**
    * 从网络下载图片
    *
    * @param ivPic
    * @param url
    */
    public void getBitmapFromNet(ImageView ivPic, String url) {
    new BitmapTask().execute(ivPic, url);// 启动AsyncTask,
    // 参数会在doInbackground中获取
    }
    /**
    * Handler和线程池的封装
    *
    * 第一个泛型: 参数类型 第二个泛型: 更新进度的泛型, 第三个泛型是onPostExecute的返回结果
    *
    * @author Kevin
    *
    */
    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);
    }
    /**
    * 更新进度, 主线程
    */
    @Override
    protected void onProgressUpdate(Void... values) {
    super.onProgressUpdate(values);
    }
    /**
    * 耗时方法结束后,执行该方法, 主线程
    */
    @Override
    protected void onPostExecute(Bitmap result) {
    if (result != null) {
    String bindUrl = (String) ivPic.getTag();
    if (url.equals(bindUrl)) {// 确保图片设定给了正确的imageview
    ivPic.setImageBitmap(result);
    mLocalCacheUtils.setBitmapToLocal(url, result);// 将图片保存在本地
    mMemoryCacheUtils.setBitmapToMemory(url, result);// 将图片保存在内存
    System.out.println("从网络缓存读取图片啦...");
    }
    }
    }
    }
    /**
    * 下载图片
    *
    * @param url
    * @return
    */
    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;
    }
    }
3.本地缓存(SD卡),一般会以MD5加密文件名
  1. public class LocalCacheUtils {
    public static final String CACHE_PATH = Environment
    .getExternalStorageDirectory().getAbsolutePath() + "/zhbj_cache_52";
    /**
    * 从本地sdcard读图片
    */
    public Bitmap getBitmapFromLocal(String url) {
    try {
    String fileName = MD5Encoder.encode(url);
    File file = new File(CACHE_PATH, fileName);
    if (file.exists()) {
    Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
    file));//decodeStream放的是输入输出流
    return bitmap;
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }
    /**
    * 向sdcard写图片
    *
    * @param url
    * @param bitmap
    */
    public void setBitmapToLocal(String url, Bitmap bitmap) {
    try {
    String fileName = MD5Encoder.encode(url);
    File file = new File(CACHE_PATH, fileName);
    File parentFile = file.getParentFile();
    if (!parentFile.exists()) {// 如果文件夹不存在, 创建文件夹
    parentFile.mkdirs();
    }
    // 将图片保存在本地
    bitmap.compress(CompressFormat.JPEG, 100,
    new FileOutputStream(file));//100是质量
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
3.内存缓存:
内存中使用LRUCache是最合适的。如果用HashMap来实现,不是不可以,但需要注意在合适的时候释放缓存。至于具体怎么释放,我没考虑过,但用软引用的问题在于,你很难控制缓存的大小,也就是说,只有等到你的内存快要撑爆,你的图片缓存才会被回收。是不是感觉傻傻的?
  1. public class MemoryCacheUtils {
    // private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new
    // HashMap<String, SoftReference<Bitmap>>();//一开始使用map,后来使用软引用
    private LruCache<String, Bitmap> mMemoryCache;
    public MemoryCacheUtils() {
    long maxMemory = Runtime.getRuntime().maxMemory() / 8;//主流都是分配16m的8/1
    mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
    @Override
    protected int sizeOf(String key, Bitmap value) {
    int byteCount = value.getRowBytes() * value.getHeight();// 获取图片占用内存大小
    return byteCount;
    }
    };
    }
    /**
    * 从内存读
    *
    * @param url
    */
    public Bitmap getBitmapFromMemory(String url) {
    // SoftReference<Bitmap> softReference = mMemoryCache.get(url);
    // if (softReference != null) {
    // Bitmap bitmap = softReference.get();
    // return bitmap;
    // }
    return mMemoryCache.get(url);
    }
    /**
    * 写内存
    *
    * @param url
    * @param bitmap
    */
    public void setBitmapToMemory(String url, Bitmap bitmap) {
    // SoftReference<Bitmap> softReference = new
    // SoftReference<Bitmap>(bitmap);
    // mMemoryCache.put(url, softReference);
    mMemoryCache.put(url, bitmap);
    }
    }

      


 
 
 
 
 
 
 

附件列表

13.缓存、三级缓存、内存溢出、AsyncTask的更多相关文章

  1. 【转】android加载大量图片内存溢出的三种解决办法

    方法一: 在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @param scalSize 缩小的倍数 * @return ...

  2. android加载大量图片内存溢出的三种方法

    android加载大量图片内存溢出的三种解决办法 方法一:  在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @para ...

  3. Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))

    因为之前项目同事使用了图片三级缓存,今天整理项目的时候发现同事还是使用了软引用(SoftRefrerence)和弱引用(WeakReference),来管理在内存中的缓存.看到这个我就感觉不对了.脑海 ...

  4. android文件缓存,并SD卡创建目录未能解决和bitmap内存溢出解决

    1.相关代码: 加入权限: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ...

  5. 关于Android中的三级缓存

    三级缓存的提出就是为了提升用户体验.当我们第一次打开应用获取图片时,先到网络去下载图片,然后依次存入内存缓存,磁盘缓存,当我们再一次需要用到刚才下载的这张图片时,就不需要再重复的到网络上去下载,直接可 ...

  6. Android 的图片异步请求加三级缓存 ACE

    使用xUtils等框架是很方便,但今天要用代码实现bitmapUtils 的功能,很简单, 1 AsyncTask请求一张图片 ####AsyncTask #####AsyncTask是线程池+han ...

  7. android 项目学习随笔十八(三级缓存)

    xUtils的BitmapUtils模块用的就是三级缓存,在项目中尽量还是应用BitmapUtils 三级缓存(机制) import com.itheima.zhsh66.R; import andr ...

  8. Android中图片的三级缓存

    为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi ...

  9. Android进阶图片处理之三级缓存方案

    图片的三级缓存 一.概述 一開始在学习Android的时候.处理图片的时候,每次获取图片都是直接从网络上面载入图片. 可是在开发项目的过程中,每次点击进入app里面,图片都要慢慢的再一次从网络上面载入 ...

随机推荐

  1. bootstrap table dataView展开行详情,p元素自动换行

    // bootstrap table 行详情展开,p元素自动换行1 .tableClass .detail-view p{ white-space: normal; }

  2. Angular官方教程采坑

    Angualar 7.0.1是现在的最新版本,教程总体来说还是不错的,但是我在跟着教程做英雄项目的时候出现了一个很明显的坑. 在教程的第6部分HTTP的内容中写到(见下图) 文档中特别注明了要使用0. ...

  3. python中的列表及numpy数组排序

    一.列表排序  # python中对列表排序有sort.sorted两种方法,其中sort是列表内置方法,其帮助文档如下:In [1]: help(sorted) Help on built-in f ...

  4. CAS SSO单点登录框架学习

    1.了解单点登录  SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...

  5. mycat读写分离性能测试

    1.    MySQL主从配置 我们的方案设计基于Mysql的主从数据复制功能,以下是基于mysql5.5以上版本最新的主从配置. 开启mysql主从数据复制,主要在mysql的my.ini文件中设置 ...

  6. java线程中的notifyAll唤醒操作

    注意: java中的notifyAll和notify都是唤醒线程的操作,notify只会唤醒等待池中的某一个线程,但是不确定是哪一个线程,notifyAll是针对指定对象里面的所有线程执行唤醒操作,指 ...

  7. ELK的高级篇(测试记录各种日志)

    一.elk架构已经完成情况情况下  访问限制: 加个x-pack插件  1)一个脚本收集多个日志,if 判断写入es的索引 [root@k8s6 conf.d]# cat file.conf inpu ...

  8. 如何方便的在windows测试python程序

    听说python的网页抓取模块很强大,我想试试看看能给我的网络优化工作带来什么大的帮助,于是跟随廖雪峰老师开始学习python(地址查看),因为我用的是window系统,这就给程序的测试带来了很多麻烦 ...

  9. Linux环境下Flask部署至apache

    https://blog.csdn.net/rainbowlemonade/article/details/79725328

  10. 关于分布式事务,XA协议的学习笔记

    XA分布式事务协议,包含二阶段提交(2PC),三阶段提交(3PC)两种实现. 1.二阶段提交方案:强一致性 事务的发起者称协调者,事务的执行者称参与者. 处理流程: 1.准备阶段 事务协调者,向所有事 ...