ImgageLoader学习总结
来源:互联网 发布:特种兵选吧 知乎 编辑:程序博客网 时间:2024/06/07 18:25
主要功能:
图片的同步加载
图片的异步加载
图片压缩
内存缓存
磁盘缓存
网络拉取
一、图片的同步加载
loadBitmap(String uri, intreqWidth, intreqHeight)
1、如果内存中已经存在,从内存中加载,bitmap = loadBitmapFromMemCache(uri)
2、如果磁盘中已经存在,从磁盘中加载,bitmap = loadBitmapFromDiskCache(uri,reqWidth,reqHeight),这个方法会先从磁盘中取出原图,然后对图片进行压缩,将压缩后的图片返回并存放在内存中
3、如果内存、磁盘中都不存在,要从网络中加载bitmap = loadBitmapFromHttp(uri,reqWidth,reqHeight)
在网络中加载到图片之后,该方法先图片存入磁盘中downloadUrlToStream(url,outputStream)(此时存储的是原图,不对图片进行压缩)
然后根据url再从磁盘中取出对应的图片loadBitmapFromDiskCache(url,reqWidth,reqHeight),这个方法首先会对图片进行压缩,将压缩后的图片返回并通过addBitmapToMemoryCache(key,bitmap)存放在内存中
4、如果磁盘缓存没有建立,则只从网络中拉取图片bitmap = downloadBitmapFromUrl(uri),不对图片进行缓存,也没对图片进行压缩,可能不太好
注意:网络访问不能在主线程中进行,所以在访问网络时要有是否在主线程中的判断
if(Looper.myLooper() == Looper.getMainLooper()) {
throw newRuntimeException("can not visit network from UI Thread.");
}
二、图片的异步加载
bindBitmap(finalString uri, finalImageView imageView, final intreqWidth, final intreqHeight)
1、给imageView设置tag,imageView.setTag(TAG_KEY_URI,uri)
2、如果内存中存在,从内存中加载进imageView中
3、如果内存中不存在,在线程池中通过loadBitmap(uri,reqWidth,reqHeight)获取图片
4、通过线程池运行loadBitmapTask,THREAD_POOL_EXECUTOR.execute(loadBitmapTask)
5、通过Handler将消息发送至主线程mMainHandler.obtainMessage(MESSAGE_POST_RESULT,result).sendToTarget(),其中Handler的代码如下(handler由主线程的looper构造而成,所以handler中代码运行在主线程中):
privateHandlermMainHandler=newHandler(Looper.getMainLooper()) {
@Override
public voidhandleMessage(Message msg) {
LoaderResult result = (LoaderResult) msg.obj;
ImageView imageView = result.imageView;
String uri = (String) imageView.getTag(TAG_KEY_URI);
if(uri.equals(result.uri)) {
imageView.setImageBitmap(result.bitmap);
}else{
Log.w(TAG,"set image bitmap,but url has changed, ignored!");
}
}
};
三、图片压缩
使用BitmapFactory将从磁盘或Resource位置的图片压缩后加载进内存中:
1、将BitmapFactor.Options的inJustDecodeBounds参数设置为true并加载图片(将inJustDecodeBounds设置为true时,BitmapFactory只会去解析图片的原始宽/高信息并不会真正地去加载图片到内存)
2、从BitmapFactory.Options中取出图片的原始宽高信息,他们对应于outWidth和outHeight参数
final intheight = options.outHeight;
final intwidth = options.outWidth;
3、根据采样率的规则(inSampleSize = 2^n)并结合目标View的所需大小(reqWidth、reqHeight)计算出采样率inSampleSize(小于reqWidth及reqHeight的最大outWidth、outHeight)
4、将BitmapFactory.Options的inJustDecodeBounds参数设为false,然后重新加载图片
bitmap = BitmapFactory.decodeFileDescriptor(fd, null, options)
代码片段:
// First decode with inJustDecodeBounds=true to check dimensions
finalBitmapFactory.Options options =newBitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeFileDescriptor(fd, null, options);
// Calculate inSampleSize
options.inSampleSize= calculateInSampleSize(options,reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds=false;
returnBitmapFactory.decodeFileDescriptor(fd, null, options);
四、内存缓存
存入内存:
private voidaddBitmapToMemoryCache(String key,Bitmap bitmap) {
if(getBitmapFromMemCache(key) ==null) {
mMemoryCache.put(key,bitmap);
}
}
从内存中获取:
privateBitmaploadBitmapFromMemCache(String url) {
finalString key = hashKeyFormUrl(url);
Bitmap bitmap = getBitmapFromMemCache(key);
returnbitmap;
}
五、磁盘缓存
这是唯一一处将图片存入磁盘的操作,发生在图片从网络上取得之后,相比存入内存,存入磁盘的操作要复杂一些,包括editor =mDiskLruCache.edit(key)、 OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX)、 editor.commit();、mDiskLruCache.flush()
代码如下:
privateBitmaploadBitmapFromHttp(String url, int reqWidth, intreqHeight)
throwsIOException {
if(Looper.myLooper() == Looper.getMainLooper()) {
throw newRuntimeException("can not visit network from UI Thread.");
}
if(mDiskLruCache==null) {
return null;
}
String key = hashKeyFormUrl(url);
DiskLruCache.Editor editor =mDiskLruCache.edit(key);
if(editor !=null) {
OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);
if(downloadUrlToStream(url,outputStream)) {
editor.commit();
}else{
editor.abort();
}
mDiskLruCache.flush();
}
returnloadBitmapFromDiskCache(url,reqWidth,reqHeight);
}
六、Adapter中view复用的错位问题
一个是要在handler中处理,当uri发生改变时,直接忽略,不对imageView进行设置:
public voidhandleMessage(Message msg) {
LoaderResult result = (LoaderResult) msg.obj;
ImageView imageView = result.imageView;
String uri = (String) imageView.getTag(TAG_KEY_URI);
if(uri.equals(result.uri)) {
imageView.setImageBitmap(result.bitmap);
}else{
Log.w(TAG,"set image bitmap,but url has changed, ignored!");
}
}
另外,在发生滑动的时候,预先设置一张默认图片将以前的图片覆盖掉:
publicViewgetView(intposition,View convertView,ViewGroup parent) {
ViewHolder holder =null;
if(convertView ==null) {
convertView =mInflater.inflate(R.layout.image_list_item,parent, false);
holder =newViewHolder();
holder.imageView= (ImageView) convertView.findViewById(R.id.image);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
ImageView imageView = holder.imageView;
finalString tag = (String)imageView.getTag();
finalString uri = getItem(position);
//是为了在滑动的时候,先设置一张默认图片将以前的图片覆盖掉
if(!uri.equals(tag)) {
imageView.setImageDrawable(mDefaultBitmapDrawable);
}
if(mIsGridViewIdle&&mCanGetBitmapFromNetWork) {
imageView.setTag(uri);
mImageLoader.bindBitmap(uri,imageView,mImageWidth,mImageWidth);
}
returnconvertView;
}
github代码地址:https://github.com/Gaoee/android-art-res/tree/master/Chapter_12
0 0
- ImgageLoader学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- 学习总结
- PS模仿欢乐颂电视剧海报的水彩效果
- HDU 5876 Sparse Graph
- jquery mobile mobileinit事件
- 环境传感器的组成及使用方法
- eclipse中如何为类快速添加多个构造方法
- ImgageLoader学习总结
- git reset soft,hard,mixed之区别深解
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- poj2828——Buy Tickets(线段树+倒插法)
- 第37课:Spark中Shuffle详解及作业
- 过滤器Filter
- 矩阵乘法实现
- 1006. Sign In and Sign Out (25)
- [n点无向图个数 分治FFT || 多项式求逆] BZOJ 3456 城市规划