图片的三级缓存
程序员文章站
2022-07-02 09:49:07
...
图片的网址
package com.example.mybitmap;
/**
* Created by 李倩 on 2017/12/11.
*/
public class ImageDataUtils {
public static String[] ImagesUtils=new String[]{
"http://tupian.enterdesk.com/2012/0615/gha/15/1337566102yPLeJh.jpg",
"http://d.hiphotos.baidu.com/zhidao/pic/item/9358d109b3de9c8252c0eeac6e81800a19d8436f.jpg",
"http://d.hiphotos.baidu.com/zhidao/pic/item/503d269759ee3d6d8ef6e5e641166d224f4adeef.jpg",
"http://e.hiphotos.baidu.com/zhidao/pic/item/ca1349540923dd54ea2076a4d309b3de9d8248af.jpg",
"http://img2.duitang.com/uploads/item/201302/02/20130202212707_4isX8.jpeg",
"http://f.hiphotos.baidu.com/zhidao/pic/item/cf1b9d16fdfaaf51be2f8bc9885494eef11f7af3.jpg",
"http://www.fosss.org/Images/2012ZhuFu/images/nmamtf_39.png",
"http://www.fosss.org/Images/2012ZhuFu/images/nmamtf_40.png",
"http://e.hiphotos.baidu.com/zhidao/pic/item/f9198618367adab4aef507b98ad4b31c8701e427.jpg",
"http://img5.imgtn.bdimg.com/it/u=334903364,3746159163&fm=21&gp=0.jpg",
"http://i1.sinaimg.cn/gm/t/i/2010-03-09/U1782P115T41D188006F756DT20100309143541.jpg",
"http://cdn.pcbeta.attachment.inimc.com/data/attachment/forum/201210/03/0028387ggklg56eel5s5es.jpg",
"http://image.tianjimedia.com/uploadImages/2012/236/S406C8D0TG39.jpg",
"http://imgsrc.baidu.com/baike/pic/item/0b46f21fbe096b6329270c190c338744ebf8acb9.jpg",
"http://www.fosss.org/Images/2012ZhuFu/images/nmamtf_27.png",
"http://i2.sinaimg.cn/gm/t/i/2011-04-14/U1782P115T41D229872F756DT20110414152419.jpg",
"http://e.hiphotos.baidu.com/zhidao/pic/item/f9dcd100baa1cd119664989dbb12c8fcc2ce2db9.jpg"
};
}
自定义的bitmap工具类
package com.example.mybitmap.bitmap;
/**
*
* 一个懂得了编程乐趣的小白,希望自己
* 能够在这个道路上走的很远,也希望自己学习到的
* 知识可以帮助更多的人,分享就是学习的一种乐趣
*
*/
import android.graphics.Bitmap;
import android.widget.ImageView;
/**
* 自定义的bitmap工具类
*/
public class MyBitmapUtils {
/**
* 网络缓存
*/
public NetCacheUtils mNetCacheUtils;
/**
* 本地缓存
*/
public SDcardCacheUtils mSdCacheUtils;
/**
* 内存缓存
*/
public MemoryCacheUtils mMemoryCacheUtils;
public MyBitmapUtils() {
mSdCacheUtils = new SDcardCacheUtils();
mMemoryCacheUtils = new MemoryCacheUtils();
mNetCacheUtils = new NetCacheUtils(mSdCacheUtils, mMemoryCacheUtils);
}
/**
* 展示图片的方法
*
* @param image
* @param url
*/
public void display(ImageView image, String url) {
//从内存中读取
Bitmap fromMemroy = mMemoryCacheUtils.getFromMemroy(url);
//如果内存中有的h话就直接返回,从内存中读取
if (fromMemroy != null) {
image.setImageBitmap(fromMemroy);
return;
}
//从本地SD卡读取
Bitmap fromSd = mSdCacheUtils.getFromSd(url);
if (fromSd != null) {
image.setImageBitmap(fromSd);
mMemoryCacheUtils.setToMemory(url, fromSd);
return;
}
//从网络中读取
mNetCacheUtils.getDataFromNet(image, url);
}
}
MemoryCacheUtils 内存缓存
package com.example.mybitmap.bitmap;
/**
* Created by 李倩 on 2017/12/11.
*/
import android.graphics.Bitmap;
import android.util.Log;
import android.util.LruCache;
/**
* 内存缓存
*/
public class MemoryCacheUtils {
/**
* LinkedHashMap<>(10,0.75f,true);
* <p/>
* 10是最大致 0.75f是加载因子 true是访问排序 false插入排序
*
*/
//private LinkedHashMap<String,Bitmap> mMemoryCache = new LinkedHashMap<>(5,0.75f,true);
private LruCache<String, Bitmap> mLruCache;
public MemoryCacheUtils() {
long maxMemory = Runtime.getRuntime().maxMemory();//最大内存 默认是16兆 运行时候的
mLruCache = new LruCache<String, Bitmap>((int) (maxMemory / 8)) {
@Override
protected int sizeOf(String key, Bitmap value) {
//int byteCount = value.getByteCount();
//得到图片字节数
// @return number of bytes between rows of the native bitmap pixels.
int byteCount = value.getRowBytes() * value.getWidth();
return byteCount;
}
};
}
/**
* 从内存中读取
*
* @param url
*/
public Bitmap getFromMemroy(String url) {
Log.d("MyBitmapUtils", "从内存中加载图片");
return mLruCache.get(url);
}
/**
* 写入到内存中
*
* @param url
* @param bitmap
*/
public void setToMemory(String url, Bitmap bitmap) {
mLruCache.put(url, bitmap);
}
}
NetCacheUtils网络缓存工具类
package com.example.mybitmap.bitmap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 网络缓存工具类
*/
public class NetCacheUtils {
/**
* 图片
*/
private ImageView mImageView;
/**
* 图片地址
*/
private String mUrl;
/**
* 本地缓存
*/
private SDcardCacheUtils mDcardCacheUtils;
/**
* 内存缓存
*/
private MemoryCacheUtils mMemoryCacheUtils;
public NetCacheUtils(SDcardCacheUtils dcardCacheUtils, MemoryCacheUtils memoryCacheUtils) {
mDcardCacheUtils = dcardCacheUtils;
mMemoryCacheUtils = memoryCacheUtils;
}
/**
* 从网络中下载图片
*
* @param image
* @param url
*/
public void getDataFromNet(ImageView image, String url) {
new MyAsyncTask().execute(image, url); //启动Asynctask,传入的参数到对应doInBackground()
}
/**
* 异步下载
* <p/>
* 第一个泛型 : 参数类型 对应doInBackground()
* 第二个泛型 : 更新进度 对应onProgressUpdate()
* 第三个泛型 : 返回结果result 对应onPostExecute
*/
class MyAsyncTask extends AsyncTask<Object, Void, Bitmap> {
/**
* 后台下载 子线程
*
* @param params
* @return
*/
@Override
protected Bitmap doInBackground(Object... params) {
//拿到传入的image
mImageView = (ImageView) params[0];
//得到图片的地址
mUrl = (String) params[1];
//将imageview和url绑定,防止错乱
mImageView.setTag(mUrl);
Bitmap bitmap = downLoadBitmap(mUrl);
return bitmap;
}
/**
* 进度更新 UI线程
*
* @param values
*/
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
/**
* 回调结果,耗时方法结束后,主线程
*
* @param bitmap
*/
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null) {
//得到图片的tag值
String url = (String) mImageView.getTag();
//确保图片设置给了正确的image
if (url.equals(mUrl)) {
mImageView.setImageBitmap(bitmap);
/**
* 当从网络上下载好之后保存到sdcard中
*/
mDcardCacheUtils.savaSd(mUrl, bitmap);
/**
* 写入到内存中
*/
mMemoryCacheUtils.setToMemory(mUrl, bitmap);
Log.d("MyBitmapUtils", "我是从网络缓存中读取的图片啊");
}
}
}
}
/**
* 下载图片
*
* @param url 下载图片地址
* @return
*/
private Bitmap downLoadBitmap(String url) {
//连接
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url)
.openConnection();
//设置读取超时
conn.setReadTimeout(5000);
//设置请求方法
conn.setRequestMethod("GET");
//设置连接超时连接
conn.setConnectTimeout(5000);
//连接
conn.connect();
//响应码
int code = conn.getResponseCode();
if (code == 200) { //请求正确的响应码是200
//得到响应流
InputStream inputStream = conn.getInputStream();
//得到bitmap对象
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
conn.disconnect();
}
return null;
}
}
SDcardCacheUtils 本地缓存
package com.example.mybitmap.bitmap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;
import com.example.mybitmap.MD5Encoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
* 本地缓存
*/
public class SDcardCacheUtils {
/**
* 我们读取内存的绝对路径
*/
public static final String CACHE_PATH = Environment
.getExternalStorageDirectory().getAbsolutePath() + "/aixuexi";
/**
* 从本地读取
* @param url
*/
public Bitmap getFromSd(String url){
String fileName = null;
try {
//得到图片的url的md5的文件名
fileName = MD5Encoder.encode(url);
} catch (Exception e) {
e.printStackTrace();
}
File file = new File(CACHE_PATH,fileName);
//如果存在,就通过bitmap工厂,返回的bitmap,然后返回bitmap
if (file.exists()){
try {
Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
Log.d("MyBitmapUtils", "从本地读取图片啊");
return bitmap;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 向本地缓存
*
* @param url 图片地址
* @param bitmap 图片
*/
public void savaSd(String url,Bitmap bitmap){
String fileName = null;
try {
//我们对图片的地址进行MD5加密,作为文件名
fileName = MD5Encoder.encode(url);
} catch (Exception e) {
e.printStackTrace();
}
/**
* 以CACHE_PATH为文件夹 fileName为文件名
*/
File file = new File(CACHE_PATH,fileName);
//我们首先得到他的符文剑
File parentFile = file.getParentFile();
//查看是否存在,如果不存在就创建
if (!parentFile.exists()){
parentFile.mkdirs(); //创建文件夹
}
try {
//将图片保存到本地
/**
* @param format The format of the compressed image 图片的保存格式
* @param quality Hint to the compressor, 0-100. 0 meaning compress for
* small size, 100 meaning compress for max quality. Some
* formats, like PNG which is lossless, will ignore the
* quality setting
* 图片的保存的质量 100最好
* @param stream The outputstream to write the compressed data.
*/
bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
MD5Encoder 加密
package com.example.mybitmap;
import java.security.MessageDigest;
/**
* Created by 李倩 on 2017/12/11.
*/
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();
}
}
MainActivity
package com.example.mybitmap;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import com.example.mybitmap.bitmap.MyBitmapUtils;
public class MainActivity extends AppCompatActivity {
private String[] mImageViews;
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageViews = ImageDataUtils.ImagesUtils;
mListView = (ListView) findViewById(R.id.listview);
mListView.setAdapter(new PhotoAdapter());
}
/**
* ListView的适配器
*/
class PhotoAdapter extends BaseAdapter {
// private BitmapUtils mBitmapUtils;
private MyBitmapUtils utils;
public PhotoAdapter() {
//mBitmapUtils = new BitmapUtils(MainActivity.this);
// mBitmapUtils.configDefaultLoadingImage(R.mipmap.defaut);
utils = new MyBitmapUtils();
}
@Override
public int getCount() {
return mImageViews.length;
}
@Override
public Object getItem(int position) {
return mImageViews[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null){
holder = new ViewHolder();
convertView = View.inflate(parent.getContext(),R.layout.photo_item_list,null);
holder.tvImage = (ImageView) convertView.findViewById(R.id.image);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//PhotoData.PhotoInfo photoInfo = getItem(position);
// holder.tvTitle.setText(photoInfo.title);
//mBitmapUtils.display(holder.tvImage,mImageViews[position]);
utils.display(holder.tvImage,mImageViews[position]);
return convertView;
}
}
static class ViewHolder{
ImageView tvImage;
}
}
布局main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context="com.example.mybitmap.MainActivity">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</RelativeLayout>
子布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="220dp"
android:src="@mipmap/t012ea2b182c5bbbc35"/>
</LinearLayout>
上一篇: Vue 整合天地图实现定位功能 代码模板