内存缓存
Java中对象的四种引用类型介绍
强引用
Java中所有实例化的对象都是强引用类型,回收时GC宁愿抛出OOM异常,也不愿回收它。
软引用 SoftReference
内存足够时,不回收。内存不够时,就回收。内存缓存就是使用这种方式缓存对象
弱引用 WeakReference
GC一出来工作就回收它
虚引用 PhantomReference
用完就消失
//MD5Utils
public class MD5Utils {
public static String getMD5Str(String str)
{
MessageDigest messageDigest = null;
try
{
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(str.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e)
{
System.out.println("NoSuchAlgorithmException caught!");
System.exit(-1);
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++)
{
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
return md5StrBuff.toString();
}
}
//内存
public class MemoryCacheUtils {
/*实现方法:
通过 HashMap<String,Bitmap>键值对的方式保存图片,key为地址,value为图片对象,但因是强引用对象,很容易造成内存溢出,可以尝试SoftReference软引用对象
通过 HashMap<String, SoftReference<Bitmap>>SoftReference 为软引用对象(GC垃圾回收会自动回收软引用对象),但在Android2.3+后,系统会优先考虑回收弱引用对象,官方提出使用LruCache
通过 LruCache<String,Bitmap> least recentlly use 最少最近使用算法
会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定
*/
private LruCache<String, Bitmap> mMemoryCache;
public MemoryCacheUtils(){
long maxMemory = Runtime.getRuntime().maxMemory()/8;
mMemoryCache = new LruCache<String,Bitmap>((int)maxMemory){
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getByteCount();
return byteCount;
}
};
}
//从内存中读图片
public Bitmap getBitmapFormMemory(String url){
//Bitmap bitmap = mMemoryCache.get(url);//1.强引用方法
/*2.弱引用方法
SoftReference<Bitmap> bitmapSoftReference = mMemoryCache.get(url);
if (bitmapSoftReference != null) {
Bitmap bitmap = bitmapSoftReference.get();
return bitmap;
}
*/
Bitmap bitmap = mMemoryCache.get(url);
return bitmap;
}
//向内存中存入图片
public void setBitmapToMemory(String url,Bitmap bitmap){
/* //mMemoryCache.put(url, bitmap);//1.强引用方法
/*2.弱引用方法
mMemoryCache.put(url, new SoftReference<>(bitmap));
*/
mMemoryCache.put(url,bitmap);
}
}
//本地
public class LocalCacheUtils {
private static final String CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
//从本地读取图片
public Bitmap getBitmapFromLocal(String url){
String fileName = null;
fileName = MD5Utils.getMD5Str(url);
File file = new File(CACHE_PATH, fileName);
try {
Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
return bitmap;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
//从网络获取图片后,保存至本地缓存
public void setBitmapToLocal(String url,Bitmap bitmap){
String fileName = MD5Utils.getMD5Str(url);
File file = new File(CACHE_PATH, fileName);
File parentFile = file.getParentFile();
if(parentFile!=null){
parentFile.mkdir();
}
//把图片保存至本地
try {
bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
//网络
public class NetCacheUtils {
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;
private static final String TAG = "NetCacheUtils";
public NetCacheUtils(LocalCacheUtils mLocalCacheUtils, MemoryCacheUtils mMemoryCacheUtils) {
this.mLocalCacheUtils = mLocalCacheUtils;
this.mMemoryCacheUtils = mMemoryCacheUtils;
}
public void getBitmapForNet(ImageView imageView,String url){
new BitmapTask().execute(imageView,url);
}
class BitmapTask extends AsyncTask<Object,Void, Bitmap>{
private ImageView imageView;
private String url;
@Override
protected Bitmap doInBackground(Object... objects) {
imageView = (ImageView) objects[0];
url = (String)objects[1];
return downLoadBitmap(url);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
Log.i(TAG, "onPostExecute: 网络进行下载图片");
//本地 内存中 分别 存入一份
mLocalCacheUtils.setBitmapToLocal(url,bitmap);
mMemoryCacheUtils.setBitmapToMemory(url,bitmap);
}
super.onPostExecute(bitmap);
}
private Bitmap downLoadBitmap(String url){
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("GET");
if(connection.getResponseCode()==200){
//图片压缩
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize=0;
options.inPreferredConfig=Bitmap.Config.ARGB_4444;
Bitmap bitmap = BitmapFactory.decodeStream(connection.getInputStream(), null, options);
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
//使用
public class MyBitmapUtils {
private NetCacheUtils mNetBitmapUtils;
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;
private static final String TAG = "MyBitmapUtils";
public MyBitmapUtils(){
mLocalCacheUtils = new LocalCacheUtils();
mMemoryCacheUtils = new MemoryCacheUtils();
mNetBitmapUtils = new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils);
}
public void disPlay(ImageView imageView,String url){
imageView.setImageResource(R.mipmap.ic_launcher_round);
Bitmap bitmap;
bitmap = mMemoryCacheUtils.getBitmapFormMemory(url);
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
Log.i(TAG, "disPlay: 从内存中获取图片了");
return;
}
bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
Log.i(TAG, "disPlay: 从本地获取图片了");
return;
}
Log.i(TAG, "disPlay: 来过");
mNetBitmapUtils.getBitmapForNet(imageView,url);
}
}