在你应用程序的UI界面加载一张图片是一件很简单的事情,但是当你需要在界面上加载一大堆图片的时候,情况就变得复杂起来。Android为我们提供了LruCache,今天我们就来学习这个缓存的知识以及原理。

目录导航

  1. LruCache缓存的实例代码
  2. LruCache缓存的原理分析
  3. 友情链接

LruCache缓存的实例代码

一、 我们建立一个简单的项目去体会LruCache的使用过程

通过http请求网络上的图片文件,然后保存在缓存中。显示图片时,先从缓存中取,如果没有,就发送请求向服务器取。项目结构如下:

aaarticlea/png;base64,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" alt="" />

二、 在AndroidManifest.xml文件中,加入网络权限的声明:

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

三、 创建一个图片加载的类,用于对缓存的一些操作,重写LruCache的sizeOf方法:

package com.example.linux.lrucachetest;

import android.graphics.Bitmap;
import android.util.LruCache; /**
* Created by huhx on 2016/4/12.
*/
public class ImageDownloader {
private static final String TAG = "TextDownload";
private LruCache<String, Bitmap> lruCache; public ImageDownloader() {
long maxMemory = Runtime.getRuntime().maxMemory();
int cacheSize = (int) (maxMemory / 8);
lruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
} // 把Bitmap对象加入到缓存中
public void addBitmapToMemory(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
lruCache.put(key, bitmap);
}
} // 从缓存中得到Bitmap对象
public Bitmap getBitmapFromMemCache(String key) {
    Log.i(TAG, "lrucache size: " + lruCache.size());
return lruCache.get(key);
} // 从缓存中删除指定的Bitmap
public void removeBitmapFromMemory(String key) {
lruCache.remove(key);
}
}

四、 在MainActivity中使用并测试LruCache:showBitmap方法是先从缓存中取,如果没有就发送http请求取得。

public void showBitmap(View view) {
Bitmap bitmap = imageDownloader.getBitmapFromMemCache("bitmap");
if (bitmap == null) {
new BitmapThread(bitmapUrl).start();
} else {
imageView.setImageBitmap(bitmap);
}
}

五、 BitmapThread的线程:从服务器拿到Bitmap对象,并加入到缓存中。

class BitmapThread extends Thread {
private String bitmapUrl; BitmapThread(String bitmapUrl) {
this.bitmapUrl = bitmapUrl;
} @Override
public void run() {
Log.i(TAG, "run: " + Thread.currentThread().getName());
Bitmap bitmap = null;
HttpURLConnection connection = null;
InputStream inputStream = null;
try {
URL url = new URL(bitmapUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET"); if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
inputStream = connection.getInputStream();
bitmap = BitmapFactory.decodeStream(inputStream);
}
imageDownloader.addBitmapToMemory("bitmap", bitmap);
handler.obtainMessage(DOWNLOAD_IMAGE, bitmap).sendToTarget();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

六、 handler处理消息,并显示图片:

private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "hanlder handleMessage: " + Thread.currentThread().getName());
switch (msg.what) {
case DOWNLOAD_IMAGE:
imageView.setImageBitmap((Bitmap) msg.obj);
break;
}
}
};

七、 从缓存中删除图片:

public void remove(View view) {
imageDownloader.removeBitmapFromMemory("bitmap");
}

八、 输出日志结果如下:

第一次点击showBitmap:

- ::21.768 -/com.example.linux.lrucachetest I/TextDownload: lrucache size:
- ::21.771 -/com.example.linux.lrucachetest I/MainActivity: run: Thread-
- ::21.816 -/com.example.linux.lrucachetest I/TextDownload: lrucache size:
- ::21.817 -/com.example.linux.lrucachetest I/MainActivity: hanlder handleMessage: main

第二次点击showBitmap:

- ::11.128 -/com.example.linux.lrucachetest I/TextDownload: lrucache size: 

点击remove之后,再点击showBitmap:

- ::47.834 -/com.example.linux.lrucachetest I/TextDownload: lrucache size:
- ::47.839 -/com.example.linux.lrucachetest I/MainActivity: run: Thread-
- ::47.895 -/com.example.linux.lrucachetest I/TextDownload: lrucache size:
- ::47.895 -/com.example.linux.lrucachetest I/MainActivity: hanlder handleMessage: main

LruCache缓存的原理分析

通过上述的案例,我们已经知道了LruCache的使用方法。接下来,我们一步步的分析它的过程以及原理。

一、 LruCache的文档描述如下:

A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection. 

二、 它的属性一方法说明如下:

public class LruCache<K, V> {
private final LinkedHashMap<K, V> map;
/** Size of this cache in units. Not necessarily the number of elements. */
private int size;
private int maxSize; private int putCount;
private int createCount;
private int evictionCount;
private int hitCount;
private int missCount;
}

文档上一些对LruCache方法的描述:

If your cached values hold resources that need to be explicitly released, override entryRemoved(boolean, K, V, V)
If a cache miss should be computed on demand for the corresponding keys, override create(K). This simplifies the calling code, allowing it to assume a value will always be returned, even when there's a cache miss.
By default, the cache size is measured in the number of entries. Override sizeOf(K, V) to size the cache in different units. For example, this cache is limited to 4MiB of bitmaps:

三、 LruCache只有一个构造方法,LruCache(int maxSize)代码如下:初始化一个LinkedHashMap

public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
}

四、 LruCache的put方法是把内容放入到缓存中去,代码如下:

public final V put(K key, V value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
} V previous;
synchronized (this) {
putCount++;
size += safeSizeOf(key, value);
previous = map.put(key, value);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
} if (previous != null) {
entryRemoved(false, key, previous, value);
} trimToSize(maxSize);
return previous;
}
其中safeSizeOf方法,是计算LruCache的已经缓存的大小,以下的sizeOf(默认返回1)方法是我们要重写的。
private int safeSizeOf(K key, V value) {
int result = sizeOf(key, value);
if (result < 0) {
throw new IllegalStateException("Negative size: " + key + "=" + value);
}
return result;
}

我们要重写sizeOf方法:

protected int sizeOf(K key, V value) {
return 1;
}

五、 LruCache的get方法是从缓存中去取得内容,代码如下:

public final V get(K key) {
if (key == null) {
throw new NullPointerException("key == null");
} V mapValue;
synchronized (this) {
     // 如果根据相应的key得到value,就增加一次命中hitCount,并且返回结果
mapValue = map.get(key);
if (mapValue != null) {
hitCount++;
return mapValue;
}
     // 否则增加一次missCount
missCount++;
} /*
* Attempt to create a value. This may take a long time, and the map
* may be different when create() returns. If a conflicting value was
* added to the map while create() was working, we leave that value in
* the map and release the created value.
*/
  // 试图根据这个key,创建一个value。这里的create(key)默认是返回null,当然这个方法是可以重写的
V createdValue = create(key);
if (createdValue == null) {
return null;
} synchronized (this) {
createCount++;
     // 如果我们重写了create(key)方法而且返回值不为空,那么将上述的key与这个返回值写入到map当中
mapValue = map.put(key, createdValue); if (mapValue != null) {
// There was a conflict so undo that last put
       // 方法放入最后put的key,value值
map.put(key, mapValue);
} else {
size += safeSizeOf(key, createdValue);
}
} if (mapValue != null) {
     // 这个方法也可以重写
entryRemoved(false, key, createdValue, mapValue);
return mapValue;
} else {
trimToSize(maxSize);
return createdValue;
}
}

六、 LruCache的remove方法是从缓存中去删除内容,并更新已经缓存的大小,代码如下:

public final V remove(K key) {
if (key == null) {
throw new NullPointerException("key == null");
} V previous;
synchronized (this) {
previous = map.remove(key);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
} if (previous != null) {
entryRemoved(false, key, previous, null);
} return previous;
}

友情链接

android基础---->LruCache的使用及原理的更多相关文章

  1. android基础---->DiskLruCache的使用及原理

    DiskLruCache是谷歌推荐的用来实现硬盘缓存的类,今天我们开始对于DiskLruCache的学习.DiskLruCache的测试代码:DiskLruCache的测试代码下载.关于FidkLru ...

  2. android基础---->JSON数据的解析

    上篇博客,我们谈到了XML两种常用的解析技术,详细可以参见我的博客(android基础---->XMl数据的解析).网络传输另外一种数据格式JSON就是我们今天要讲的,它是比XML体积更小的数据 ...

  3. 基础4 Android基础

    基础4 Android基础 1. Activity与Fragment的生命周期. Activity生命周期 打开应用 onCreate()->onStart()->onResume 按BA ...

  4. Android基础总结(8)——服务

    服务(Service)是Android中实现程序后台运行的解决方案,它非常适合用于去执行哪些不需要和用户交互而且还要长期运行的任务.服务的运行不依赖任何用户界面,即使当程序被切换到后台,或者用户打开了 ...

  5. android基础---->IntentService的使用

    这一篇博客,我们开始前台服务与IntentServie源码分析的学习,关于service的生命周期及其简单使用,请参见我的博客:(android基础---->service的生命周期) 目录导航 ...

  6. Android逆向系列文章— Android基础逆向(6)

    本文作者:HAI_ 0×00 前言 不知所以然,请看 Android逆向-Android基础逆向(1) Android逆向-Android基础逆向(2) Android逆向-Android基础逆向(2 ...

  7. 图文详解 Android Binder跨进程通信机制 原理

    图文详解 Android Binder跨进程通信机制 原理 目录 目录 1. Binder到底是什么? 中文即 粘合剂,意思为粘合了两个不同的进程 网上有很多对Binder的定义,但都说不清楚:Bin ...

  8. Android基础夯实--重温动画(三)之初识Property Animation

    每个人都有一定的理想,这种理想决定着他的努力和判断的方向.就在这个意义上,我从来不把安逸和快乐看作生活目的的本身--这种伦理基础,我叫它猪栏的理想.--爱因斯坦 一.摘要 Property Anima ...

  9. Android基础新手教程——4.1.1 Activity初学乍练

    Android基础新手教程--4.1.1 Activity初学乍练 标签(空格分隔): Android基础新手教程 本节引言: 本节開始解说Android的四大组件之中的一个的Activity(活动) ...

随机推荐

  1. YAML的使用

    YAML 语言教程 编程免不了要写配置文件,怎么写配置也是一门学问.                                      YAML 是专门用来写配置文件的语言,非常简洁和强大,远 ...

  2. GPU硬件加速原理 /转

    现代浏览器大都可以利用GPU来加速页面渲染.每个人都痴迷于60桢每秒的顺滑动画.在GPU的众多特性之中,它可以存储一定数量的纹理(一个矩形的像素点集合)并且高效地操作这些纹理(比如进行特定的移动.缩放 ...

  3. iOS边练边学--UITableViewCell的常见属性设置

    // 取消选中的样式(常用) 让当前 cell 按下无反应 cell.selectionStyle = UITableViewCellSelectionStyleNone; // 设置选中的背景色,U ...

  4. @RequestMapping @ResponseBody 和 @RequestBody 注解的用法与区别

    1.@RequestMapping 国际惯例先介绍什么是@RequestMapping,@RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上.用于类上,表示类中的所有响应 ...

  5. Jquery判断某字符串中是否包含某个字符

    if(!(to_city_value.indexOf("(")>0){ //code..... }

  6. [R语言统计]频数表

    频数表在统计学中是一个非常基本并且重要的概念,我们这里就来讲解它的基本用法. 首先我们需要载入数据,并查看数据的基本信息 install.packages('vcd') #安装vcd包,其中有可以利用 ...

  7. msysgit使用方法

    安装好后运行"Git Bash",出现命令框. 输入 ssh-keygen -t rsa -C “your_email@youremail.com” 会提示SSH Public K ...

  8. ANSI 标准是为了确保 C++ 的便携性

    ANSI 标准ANSI 标准是为了确保 C++ 的便携性 —— 您所编写的代码在 Mac.UNIX.Windows.Alpha 计算机上都能通过编译. 由于 ANSI 标准已稳定使用了很长的时间,所有 ...

  9. par函数的ann 参数-控制图片的注释信息

    ann 参数控制图片的x轴和y轴标签以及标题是否显示 默认值为TRUE, 所以图片有对应的信息时,会显示出来,代码示例 plot(1:5, 1:5, main = "title", ...

  10. 【matlab】运动目标检测之"背景差分算法“

    clear; clc; i1=imread('D:\Work\1.png'); i2=imread('D:\Work\2.png'); i1=rgb2gray(i1); i2=rgb2gray(i2) ...