Android进阶之Bitmap的高效加载

一、Bitmap的加载

BitmapFactory提供了四个方法:

  • docodeFiles
  • decodeResource
  • decodeStream
  • decodeByteArray

二、Bitmap的高效加载

采用Bitmap.Options来加载所需尺寸的图片,主要使用它的inSampleSize参数,当inSampleSize大于1缩放。(inSampleSize会向下去2的指数)
高效加载图片的流程:

  1. 将BitmapFactory.Options的inJustDecodeBuunds设为true并加载图片
  2. 从Bitmap.Options中取出图片的宽高(outHeight,outWidth)
  3. 结合ImageView的宽高计算采样率
  4. 将BitmapFatory.Options中的inJustDecodeBounds设为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用于内存缓存
DiskLruCache用于存储设备缓存

(1)LruCache

LruCache是Android提供的一个缓存类,它是一个泛型类,内部采用LinkedHashMap以强引用的方式存储外界对象。
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();
}
}

添加一个缓存对象

mMemoryCache.put(key,value);

获取一个缓存对象

mMemory.get(key);

(2)DiskLruCache

DiskLruCache用于设备的存储,及磁盘缓存。需要添加依赖:

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所对应的Key,再根据key通过edit()方法获取Editor对象,一般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对象

String key=hashFormUrl(url);
DiskLruCache.Editor editor=mDiskLruCache.edit(key);
if(editor!=null){
OutputStream outputStream=editor.newOutputStream(DISK_CACHE_INDEX);
}

存入缓存对象

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();//由于使用流解析存在问题,所以采取流对应的文件描述符来解析
bitmap=decodeSampleedBitmapFromFileDescriptor(fileDescriptor,repWidth,repHeight);//自己写的高效加载图片的方法和前面的一样只是解析方法不一样
if(bitmap!=null){
addBitmapTomemoryCache(key,bitmap);
}
}

最后

如果你看到了这里,觉得文章写得不错就给个赞呗!欢迎大家评论讨论!如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足,定期免费分享技术干货。喜欢的小伙伴可以关注一下哦。谢谢!

发布了289 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45365889/article/details/102594728