1.关于JAVA中的对象引用,分为:强、软、弱、虚。
2.关于JAVA的强引用与软引用:
(1)强引用:JVM不会回收任何具有强引用的对象,内存空间不足时,将抛出OOM异常;
(2)软引用:在内存不足时,JVM将会回收掉具有软引用的对象,从而满足程序运行的需求,以此避免出现OOM导致的程序崩溃。
3.内存缓存部分:
(1)强引用存储区:
LruCache<String,Bitmap> cache = new LruCache<String,Bitmap>();
(2)软引用存储区:
HashMap<String,Bitmap> softBitmapCache = new HashMap<String,SoftReference<Bitmap>>();
5.关于LruCache类的理解:
这个类其实就是一个哈希表,存储键值对。
值得注意的是:LruCache内部存储的图片内存数量超过上限以后,将采用LRU算法删除部分图片。LRU:Least-Recently-Used。
Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。当cache已满的时候加入新的item时,在队列尾部的item会被回收。
6.从文件缓存中获取图片的流程:
强引用存储区---->软引用存储区---->文件存储----->网络获取---->显示UI
7.问题:在内存缓存中获取图片时,为什么先在强引用存储区查找,再去软引用存储区查找?
答:强引用存储区存储的图片,有上限,超过上限将会采用LRU算法进行删除;软引用存储区的图片,在内存不足时,JVM将会自动删除部分图片。
三级缓存的过程:(以ImageLoader为例)
手机内存和SD卡都可以看成键值对储存,key:图片网址url,value:图片bitmap。
①使用LruCache缓存类,并给它定义空间大小,手机内存的1/8;
//定义空间
int max= (int) (Runtime.getRuntime().maxMemory()/8);
//初始化LruCache对象
final LruCache<String, Bitmap> lruCache=new LruCache<String, Bitmap>(max){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
②把图片压缩到SD卡设定的文件夹中(bitmap.compress),压缩大小可以自己修改方法中的第二个参数实现。
public static void setData(Bitmap bitmap, String fileName){
String path=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+fileName+".jpg";
File file=new File(path);
try {
FileOutputStream fos=new FileOutputStream(file);
//bitmap的压缩,实际的图片其实没有被压缩,只是把压缩后的数据保存到fos中了。第二个参数如果是100,表示没有被压缩。
bitmap.compress(Bitmap.CompressFormat.JPEG,1,fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
③使用ImageLoader.ImageCache对象的putBitmap()和getBitmap()方法,分别执行存入缓存和从缓存中取出;
ImageLoader.ImageCache imageCache= new ImageLoader.ImageCache() {
@Override
public Bitmap getBitmap(String url) {
if(External.isUsed()){
Bitmap bitmap=External.getData(url);
if(bitmap!=null){
return bitmap;
}else {
return lruCache.get(url);
}
}else {
return lruCache.get(url);
}
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
if(External.isUsed()){
External.setData(bitmap, url);
lruCache.put(url, bitmap);
}else {
lruCache.put(url, bitmap);
}
}
};
ImageLoader imageLoader=new ImageLoader(MyApp.getRequestQueue(), imageCache);
return imageLoader;
}
<pre style="background-color:#ffffff;color:#000000;font-family:'Consolas';font-size:13.5pt;"><span style="font-family:KaiTi_GB2312;">最后附上完整代码:
文件储存(SD卡)的存取
</span><pre name="code" class="java">package com.example.administrator.cache;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created by Administrator on 2016/7/9.
*/
public class External {
public static boolean isUsed(){
String state= Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
return true;
}
return false;
}
public static void setData(Bitmap bitmap, String fileName){
String path=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+fileName+".jpg";
File file=new File(path);
try {
FileOutputStream fos=new FileOutputStream(file);
//bitmap的压缩,实际的图片其实没有被压缩,只是把压缩后的数据保存到fos中了。第二个参数如果是100,表示没有被压缩。
bitmap.compress(Bitmap.CompressFormat.JPEG,1,fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static Bitmap getData(String fileName){
String path=Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+fileName+".jpg";
File file=new File(path);
FileInputStream fis=null;
ByteArrayOutputStream bos=null;
try {
fis=new FileInputStream(file);
bos=new ByteArrayOutputStream();
int len=0;
byte[] b=new byte[1024];
while ((len=fis.read(b))!=-1){
bos.write(b,0,len);
bos.flush();
}
byte[] bytes=bos.toByteArray();
Bitmap bitmap= BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
return bitmap;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
ImageLoader的二级缓存(三级缓存有空会补上)
package com.example.administrator.cache;
import android.graphics.Bitmap;
import android.util.LruCache;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
/**
* Created by Administrator on 2016/7/9.
*/
public class FindImage {
public static ImageLoader getLoader(RequestQueue queue){
//定义空间
int max= (int) (Runtime.getRuntime().maxMemory()/8);
//初始化LruCache对象
final LruCache<String, Bitmap> lruCache=new LruCache<String, Bitmap>(max){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
ImageLoader.ImageCache imageCache= new ImageLoader.ImageCache() {
@Override
public Bitmap getBitmap(String url) {
if(External.isUsed()){
Bitmap bitmap=External.getData(url);
if(bitmap!=null){
return bitmap;
}else {
return lruCache.get(url);
}
}else {
return lruCache.get(url);
}
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
if(External.isUsed()){
External.setData(bitmap, url);
lruCache.put(url, bitmap);
}else {
lruCache.put(url, bitmap);
}
}
};
ImageLoader imageLoader=new ImageLoader(MyApp.getRequestQueue(), imageCache);
return imageLoader;
}
}