一、Bitmap的加載
BitmapFactory提供了四個(gè)方法:
- docodeFiles
- decodeResource
- decodeStream
- decodeByteArray
二、Bitmap的高效加載
采用Bitmap.Options來(lái)加載所需尺寸的圖片,主要使用它的inSampleSize參數(shù),當(dāng)inSampleSize大于1縮放。(inSampleSize會(huì)向下去2的指數(shù))
高效加載圖片的流程:
- 將BitmapFactory.Options的inJustDecodeBuunds設(shè)為true并加載圖片
- 從Bitmap.Options中取出圖片的寬高(outHeight,outWidth)
- 結(jié)合ImageView的寬高計(jì)算采樣率
- 將BitmapFatory.Options中的inJustDecodeBounds設(shè)為false并加載圖片
示例:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView image=findViewById(R.id.image1);
image.setImageBitmap(sampleDecodeFromResourse(getResources(),R.mipmap.dog,200,200));
}
public static Bitmap sampleDecodeFromResourse(Resources res,int resId,int repWidth,int repHeight){
final BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeResource(res,resId,options);
options.inSampleSize=computeInSampleSize(options,repWidth,repHeight);
options.inJustDecodeBounds=false;
Bitmap bitmap=BitmapFactory.decodeResource(res,resId,options);
return bitmap;
}
public static int computeInSampleSize(BitmapFactory.Options options,int repWidth, int repHeight){
final int width=options.outWidth;
final int height=options.outHeight;
int inSampleSize=1;
if(width>repWidth||height>repHeight){
int sampleWidth=((int)width/repWidth)%2==0?width/repWidth+2:width/repWidth+1;
int sampleHeight=((int)height/repHeight)%2==0?height/repHeight+2:height/repHeight+1;
inSampleSize=(int)Math.max(sampleWidth,sampleHeight);
}
return inSampleSize;
}
}
三、Android中的緩存策略
常用的緩存算法LRU算法,包括:LruCache和DiskLruCache
LruCache用于內(nèi)存緩存
DiskLruCache用于存儲(chǔ)設(shè)備緩存
(1)LruCache
LruCache是Android提供的一個(gè)緩存類(lèi),它是一個(gè)泛型類(lèi),內(nèi)部采用LinkedHashMap以強(qiáng)引用的方式存儲(chǔ)外界對(duì)象。
LruCache典型初始化:
int maxMemory=(int)(Runtime.getRuntime().maxMemory()/1024);
int cacheSize=maxMemory/8;
mMemoryCache=new LruCache<String,Bitmap>(cacheSize){
protected int sizeOf(String key,Bitmap bitmap){
return bitmap.getByteCount();
}
}
添加一個(gè)緩存對(duì)象
mMemoryCache.put(key,value);
獲取一個(gè)緩存對(duì)象
mMemory.get(key);
(2)DiskLruCache
DiskLruCache用于設(shè)備的存儲(chǔ),及磁盤(pán)緩存。需要添加依賴(lài):
implementation 'com.jakewharton:disklrucache:2.0.2'
DiskLruCache的建立:
Private static final int CACHE_SIZE=1024*1024*50;
File diskCacheDir=getDiskCacheDir(mContext,"bitmap");
if(!diskCacheDir.exists())
首先獲取Url所對(duì)應(yīng)的Key,再根據(jù)key通過(guò)edit()方法獲取Editor對(duì)象,一般key取url的MD5值
private String hashKeyFormUrl(String url){
String hashKey;
try{
final MessageDigest mDigest=MessageDigest.getInstance("MD5");
mDigest.upDtate(url.getByte());
hashKey=bytesToHexString(mDigest.digest());
}catch(NoSuchAlgorithmException e){
hashKey=String.valueOf(url.hashCode());
}
return hashKey;
}
private String bytesToHexString(byte[] bytes){
StringBuffer buffer=new StringBuffer();
for(int i=0;i<bytes.length;i++){
String hex=Integer.toHexString(0xFF&bytes[i]);
if(hex.length==1){
buffer.append('0');
}
buffer.append(hex);
}
return buffer;
}
獲取Editor對(duì)象
String key=hashFormUrl(url);
DiskLruCache.Editor editor=mDiskLruCache.edit(key);
if(editor!=null){
OutputStream outputStream=editor.newOutputStream(DISK_CACHE_INDEX);
}
存入緩存對(duì)象
public boolean downloadUrlToStream(String url,OutputStream outputStream){
HttpURLConnection connection=null;
BufferedOutputStream out=null;
BufferedInputStream int=null;
try{
final URL url=new URL(url);
connection=(HttpURLConnection)url.openConnection();
in=new BufferedInputStream(connection.getInputStream(),1024*10);
out=new BufferedOutputStream(output,1024*10);
int b;
while((b=in.read())!=-1){
out.write(b);
}
return true;
}catch(IOException e){
e.printStackTrace();
}finally{
if(connection!=null){
connection.disConnection();
}
if(in!=null){
try{
in.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(out!=null){
try{
out.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
提交
OutputStream outputStream=editor.newOutputStream(DISK_CACHE_INDEX);
if(downloadUrlToStream(url,outputStream)){
editor.commit();
}else{
editor.abort();
}
mDiskLruCache.flush();
提取
Bitmap bitmp=null;
String key=hashKeyFormUrl(url);
DiskLruCache.Snapshot snapshot=mDiskLruCache.get(key);
if(snapshot!=null){
FileInputStream fileInputStream=(FileInputStream)snapshot.getInputStream(DISK_CACHE_INDEX);
FileDescriptor fileDescriptor=fileInputStream.getFD();//由于使用流解析存在問(wèn)題,所以采取流對(duì)應(yīng)的文件描述符來(lái)解析
bitmap=decodeSampleedBitmapFromFileDescriptor(fileDescriptor,repWidth,repHeight);//自己寫(xiě)的高效加載圖片的方法和前面的一樣只是解析方法不一樣
if(bitmap!=null){
addBitmapTomemoryCache(key,bitmap);
}
}