Bitmap三级缓存+二次采样
三级缓存
优缺点:
优点: 省流量,一定程度可以离线浏览
缺点:会吃内存空间 (一般手机app都会有清除缓存功能)
原理:
把要加载的图片从内存到文件到网络依次查找
假如内存没有则从文件查找
假如文件没有则从网络下载
至于如何对于图片的统一,暂未学习只是简单了解
代码:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
先添加权限
内存工具类:
//TODO 获得手机的最大内存
static long maxSize=Runtime.getRuntime().maxMemory();
//TODO 1:实例化一个内存对象
static LruCache<String, Bitmap> lruCache=new LruCache<String,Bitmap>((int) (maxSize/8)){//分配给最大内存的1/8
//返回每个图片的大小
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
/****
*
* @param key 键 图片在内存中的名字
* @param bitmap 值
*/
public static void setBitmap(String key,Bitmap bitmap){
lruCache.put(key,bitmap);
}
public static Bitmap getBitmap(String key){
return lruCache.get(key);
}
存储工具类:
public static void setBitmap(String filepath, Bitmap bitmap){
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//参数一 图片的格式 JPG PNG 参数二 质量 0-100 参数三 输出流
try {
bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(filepath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
/***
* 根据路径获得Bitmap对象
* @param filepath 文件路径
* @return Bitmap对象
*/
public static Bitmap getBitmap(String filepath){
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
Bitmap bitmap = BitmapFactory.decodeFile(filepath);
return bitmap;
}
return null;
}
网络工具类:
public static Bitmap getBitmap(String url){
Bitmap bitmap = null;//直接获取异步返回的结果
try {
bitmap = new MyTask().execute(url).get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return bitmap;
}
static class MyTask extends AsyncTask<String,String,Bitmap>{
@Override
protected Bitmap doInBackground(String... strings) {
try {
URL url = new URL(strings[0]);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
if(urlConnection.getResponseCode()==200){
InputStream inputStream = urlConnection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
这里是利用异步来完成的
主代码:
Bitmap bitmap = LruUtils.getBitmap("czn");
if(bitmap==null){
//TODO 2:从SD卡获取
bitmap=SDUtils.getBitmap("/sdcard/Pictures/czn.jpg");
if(bitmap==null){
//TODO 3:从网络获取
bitmap=NetUtils.getBitmap("http://pic1.win4000.com/wallpaper/e/50d80458e1373.jpg");
if(bitmap==null){
Toast.makeText(MainActivity.this, "你个穷鬼,没忘了", Toast.LENGTH_SHORT).show();
}else{
img.setImageBitmap(bitmap);
LruUtils.setBitmap("czn",bitmap);
SDUtils.setBitmap("/sdcard/Pictures/czn.jpg",bitmap);
Toast.makeText(MainActivity.this, "从网络获取的", Toast.LENGTH_SHORT).show();
}
}else {
img.setImageBitmap(bitmap);
LruUtils.setBitmap("czn",bitmap);
Toast.makeText(MainActivity.this, "从SD卡中获取的", Toast.LENGTH_SHORT).show();
}
}else{
img.setImageBitmap(bitmap);
Toast.makeText(MainActivity.this, "从内存中获得去", Toast.LENGTH_SHORT).show();
}
二次采样
优缺点:
优点:当手机加载图片时,假如加载原图,则会对于手机内存进行极大地占用,导致内存溢出,而二次采样
则通过一定的比率来使图片进行缩小,使视觉上图片的差距不大,但是则会极大地节省内存和空间
缺点: 关系不大
原理:
第一次:获取图片的压缩比,通过图片的宽和高结合控件来计算出缩放比
第二次:根据第一次缩放比,来对于图片进行真正的缩放
一般第一步的缩放规则是共同认可的 2的幂次
代码:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds=true;//设置只采边框
BitmapFactory.decodeByteArray(data,0,data.length,options);//采样
int outWidth = options.outWidth;//获得原图的宽
int outHeight = options.outHeight;//获得原图的高
//计算缩放比例
int size=1;
while(outWidth/size>100||outHeight/size>100){
size*=2;
}
//TODO 2:第二次采样:按照比例才像素
options.inJustDecodeBounds=false;//设置只采边框为fasle
options.inSampleSize=size;//设置缩放比例
Bitmap bitmap=BitmapFactory.decodeByteArray(data,0,data.length,options);//采样
Bitmap的质量压缩
方法
Bitmap.compress(CompressFormat format, int quality, OutputStream stream)
参数一:Bitmap被压缩成的图片格式
参数二:压缩的质量控制,范围0~100
参数三:输出流
代码:
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//获得SD卡的跟路径
File file=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file1=new File(file,name);
//存储图片:bitmap对象---->SD卡
try {
//参数一 图片的格式 参数二 图片质量 0-100 参数三:输出流
bitmap.compress(Bitmap.CompressFormat.JPEG,50,new FileOutputStream(file1));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
将一张Bitmap图片采用50%质量压缩到SD卡中