今天翻看旧文件的时候不经意间看到了以前写的图片加载文件,所以拿出来重新理一理。
思路:请求图片优先级:内存缓存》本地缓存》网络
给imageView设置图片的方法:
根据图片请求优先级来,
/**
*
* @param imageView 设置图片的控件
* @param context 上下文
* @param url 图片资源路径
*/
public static void setBitmapFromCache(ImageView imageView,Context context,String url){
if(TextUtils.isEmpty(url)){
return;
}
Bitmap bitmap=null;
//先从内存缓存中查找图片资源
bitmap=getBitmapFromMemoryCache(url);
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
return;
}
//再从应用的缓存目录中查找图片
bitmap=getBitmapFormFileCache(context,url);
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
return;
}
//再从网络上去异步请求
getBitmapAsyncLoad(imageView,url,context);
}
然后分别看一下三个请求方法的具体实现:
1.内存缓存:
//从内存缓存中获取bitmap
private static Bitmap getBitmapFromMemoryCache(String url) {
Bitmap bitmap=null;
if(url!=null){
bitmap=lruCache.get(url);
}
return bitmap;
}
2.本地缓存:
//从文件缓存(应用的缓存目录)获得数据
private static Bitmap getBitmapFormFileCache(Context context,String url) {
Bitmap bitmap=null;
String fileName= url.substring(url.lastIndexOf("/")+1);//只截取最后一级文件名,如:sdcard/pics/demo.jpg截取后-->>demo.jpg
//获得应用的缓存目录
File cacheDir=context.getCacheDir();
if(cacheDir!=null){
File[] files=cacheDir.listFiles();
for(int i=0;i<files.length;i++){
if(files[i].getName().equals(fileName)){
bitmap=BitmapFactory.decodeFile(files[i].getAbsolutePath());
return bitmap;
}
}
}
return bitmap;
}
3.从网络请求图片资源,并在请求成功后将bitmap分别存入内存缓存和本地缓存中:
使用基础网络请求框架HttpURLConnection和异步任务AsyncTask实现异步网络请求:
private static void getBitmapAsyncLoad(ImageView imageView, String url,Context context) {
MyAsyncTask task=new MyAsyncTask(context, imageView);
task.execute(url);
}
static class MyAsyncTask extends AsyncTask<String, Void, Bitmap>{
Context context;
ImageView imageView=null;
public MyAsyncTask(Context context,ImageView imageview) {
this.context=context;
this.imageView_header=imageview;
}
@Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap=null;
String path=params[0];
try {
URL url=new URL(path);
HttpURLConnection connection=(HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
connection.setDoInput(true);
if(connection.getResponseCode()==200){
InputStream inputStream= connection.getInputStream();
//把返回的图片资源按比例缩放处理
bitmap=compressBitmap(inputStream);
//存入缓存
if(bitmap!=null){
//放到内存缓存中
lruCache.put(path, bitmap);
//放到应用缓存中
bitmapCacheFile(bitmap,path,context);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
super.onPostExecute(result);
}
其中用到的图片压缩方法:
private Bitmap compressBitmap(InputStream inputStream) {
byte[] datas=getBytesFromStream(inputStream);
BitmapFactory.Options options=new BitmapFactory.Options();
//对二进制数据解码时仅做图片的边界处理
options.inJustDecodeBounds=true;
BitmapFactory.decodeByteArray(datas, 0, datas.length, options);
//边界的宽高
int outWidth=options.outWidth;
int outHeight=options.outHeight;
int targetWidth=70;
int targetHeight=70;
int wbl=outWidth/targetWidth;
int hbl=outHeight/targetHeight;
int bl=wbl>hbl?wbl:hbl;
if(bl<0){
bl=1;
}
options.inSampleSize=bl;
options.inJustDecodeBounds=false;
Bitmap bitmap=BitmapFactory.decodeByteArray(datas, 0, datas.length, options);
return bitmap;
}
//从输入流提取字节数组
private static byte[] getBytesFromStream(InputStream inputStream){
byte[] datas=null;
try{
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
byte[] buffer=new byte[1024];
int len=0;
while((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer, 0, len);
}
datas=outputStream.toByteArray();
outputStream.close();
}catch(Exception ex){
ex.printStackTrace();
}
return datas;
}
网络请求成功后将bitmap存入本地的方法:
private void bitmapCacheFile(Bitmap bitmap, String path,Context context) throws FileNotFoundException {
File cacheFile=context.getCacheDir();
if(!cacheFile.exists()){
cacheFile.mkdirs();
}
String fileName=path.substring(path.lastIndexOf("/")+1);
File file=new File(cacheFile,fileName);
OutputStream stream=new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
}
最后别忘了加上内存缓存设置:
static LruCache<String, Bitmap> lruCache=null;
static{
int maxsize=4*1024*1024;
lruCache=new LruCache<String, Bitmap>(maxsize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight();
}
};
}