Created
October 21, 2014 11:15
-
-
Save easternHong/2a054b82605cb9d264eb to your computer and use it in GitHub Desktop.
使用IMAGE_CACHE,大幅度提升ListView GridView性能
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.hunt.listviewdemo; | |
import java.util.ArrayList; | |
import java.util.List; | |
import android.content.Context; | |
import android.graphics.Bitmap; | |
import android.graphics.BitmapFactory; | |
import android.os.Environment; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.view.animation.AlphaAnimation; | |
import android.widget.ImageView; | |
import android.widget.TextView; | |
import cn.trinea.android.common.entity.CacheObject; | |
import cn.trinea.android.common.entity.FailedReason; | |
import cn.trinea.android.common.service.impl.ImageCache; | |
import cn.trinea.android.common.service.impl.ImageCache.CompressListener; | |
import cn.trinea.android.common.service.impl.ImageMemoryCache.OnImageCallbackListener; | |
import cn.trinea.android.common.service.impl.PreloadDataCache.OnGetDataListener; | |
import cn.trinea.android.common.service.impl.RemoveTypeLastUsedTimeFirst; | |
import cn.trinea.android.common.util.FileUtils; | |
import cn.trinea.android.common.util.ObjectUtils; | |
import com.hunt.listviewdemo.support.debug.AppLogger; | |
/** | |
* 使用ImageCache 只需要三个步骤 1.添加: <uses-permission | |
* android:name="android.permission.INTERNET" /> <uses-permission | |
* android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission | |
* android:name="android.permission.ACCESS_NETWORK_STATE" /> 2 a.加载ImageView // | |
* 获取全局访问点 public static final ImageCache IAMGE_CACHE = | |
* CacheManager.getImageCache(); b.静态代码块:回调。3.需要加载图片的地方使用get(imageUrl, | |
* imageView); | |
* | |
* @author hunt | |
* | |
*/ | |
public class MyAdapter extends ArrayAdapter<Integer> { | |
private List<String> imageUrlList; | |
private void initImageUrlList() { | |
imageUrlList = new ArrayList<String>(); | |
imageUrlList | |
.add("http://farm8.staticflickr.com/7409/9148527822_36fa37d7ca_z.jpg"); | |
imageUrlList | |
.add("http://farm4.staticflickr.com/3755/9148527824_6c156185ea.jpg"); | |
imageUrlList | |
.add("http://farm8.staticflickr.com/7318/9148527808_e804baef0b.jpg"); | |
imageUrlList | |
.add("http://farm8.staticflickr.com/7318/9146300275_5fe995d123.jpg"); | |
imageUrlList | |
.add("http://farm8.staticflickr.com/7288/9146300469_bd3420c75b_z.jpg"); | |
imageUrlList | |
.add("http://farm8.staticflickr.com/7351/9148527976_8a4e75ae87.jpg"); | |
imageUrlList | |
.add("http://farm3.staticflickr.com/2888/9148527996_f05118d7de_o.jpg"); | |
imageUrlList | |
.add("http://farm3.staticflickr.com/2863/9148527892_31f9377351_o.jpg"); | |
imageUrlList | |
.add("http://farm8.staticflickr.com/7310/9148528008_8e8f51997a.jpg"); | |
imageUrlList | |
.add("http://farm3.staticflickr.com/2849/9148528108_dfcda19507.jpg"); | |
imageUrlList | |
.add("http://farm4.staticflickr.com/3739/9148528022_e9bf03058f.jpg"); | |
imageUrlList | |
.add("http://img.article.pchome.net/00/40/12/85/pic_lib/s960x639/wondergirl12s960x639.jpg"); | |
imageUrlList | |
.add("http://img5.imgtn.bdimg.com/it/u=1446812229,652623722&fm=23&gp=0.jpg"); | |
imageUrlList | |
.add("http://img2.duitang.com/uploads/item/201202/24/20120224223729_smMTH.thumb.600_0.jpg"); | |
imageUrlList | |
.add("http://pic.pedaily.cn/resource/201301/201301271941050.jpg"); | |
imageUrlList | |
.add("http://img2.duitang.com/uploads/item/201202/24/20120224223729_smMTH.thumb.600_0.jpg"); | |
imageUrlList | |
.add("http://img1.imgtn.bdimg.com/it/u=522765366,4089201389&fm=23&gp=0.jpg"); | |
imageUrlList | |
.add("http://wenwen.sogou.com/p/20090517/20090517143707-1281434145.jpg"); | |
} | |
private LayoutInflater layoutInflater; | |
private int[] iamgeId = { R.drawable.img_nature2, R.drawable.img_nature3, | |
R.drawable.img_nature4, R.drawable.img_nature5, }; | |
private int size = 500; | |
// 获取全局访问点 | |
// public static final ImageCache IAMGE_CACHE = | |
// CacheManager.getImageCache(); | |
public static final ImageCache IAMGE_CACHE = new ImageCache(128, 512); | |
public MyAdapter(Context mContext) { | |
initImageUrlList(); | |
layoutInflater = LayoutInflater.from(mContext); | |
for (int i = 0; i < size; i++) | |
add(i); | |
} | |
@Override | |
public int getCount() { | |
// TODO Auto-generated method stub | |
return size; | |
} | |
@Override | |
public Integer getItem(int position) { | |
// TODO Auto-generated method stub | |
return null; | |
} | |
@Override | |
public long getItemId(int position) { | |
// TODO Auto-generated method stub | |
return position; | |
} | |
@Override | |
public View getView(int position, View convertView, ViewGroup parent) { | |
// TODO Auto-generated method stub | |
ViewHolder holder; | |
if (convertView == null) { | |
// this is the content layout | |
convertView = layoutInflater.inflate(R.layout.item, null); | |
holder = new ViewHolder(); | |
holder.appicon = (ImageView) convertView.findViewById(R.id.im); | |
holder.appName = (TextView) convertView.findViewById(R.id.tv); | |
// .... | |
convertView.setTag(holder); | |
} else { | |
holder = (ViewHolder) convertView.getTag(); | |
} | |
holder.appName.setText("" + position); | |
// String imageUrl = imageUrlList.get(position % imageUrlList.size()) | |
// .toString(); | |
final String imagePath = Environment.getExternalStorageDirectory() | |
+ "/DCIM/Flickr/2014-09-27_10-44-06.jpg"; | |
holder.appicon.setTag(imagePath); | |
if (!IAMGE_CACHE.get(imagePath, holder.appicon)) { | |
// 设置默认图片 | |
holder.appicon.setImageResource(R.drawable.ic_launcher); | |
} | |
return convertView; | |
} | |
private static class ViewHolder { | |
ImageView appicon; | |
TextView appName; | |
} | |
// 静态代码块,当类被载入时,调用,而且只被调用一次。 | |
static { | |
// 图片加载回调接口,使用内存缓存 | |
OnImageCallbackListener imageCallBack = new OnImageCallbackListener() { | |
private static final long serialVersionId = 1L; | |
// callback function before get image ,run on ui thread | |
@Override | |
public void onPreGet(String imageUrl, View view) { | |
// TODO Auto-generated method stub | |
AppLogger.d("pre get "); | |
} | |
// 成功加载 | |
@Override | |
public void onGetSuccess(String imageUrl, Bitmap loadedImage, | |
View view, boolean isInCache) { | |
// TODO Auto-generated method stub | |
if (view != null && loadedImage != null | |
&& view instanceof ImageView) { | |
ImageView image = (ImageView) view; | |
// 获得之前设置的tag | |
String imageUrlTag = (String) image.getTag(); | |
if (ObjectUtils.isEquals(imageUrl, imageUrlTag)) | |
image.setImageBitmap(loadedImage); | |
// setImageScale(imageUrlTag, image); | |
if (!isInCache) { | |
image.startAnimation(getInAlphaAnimation(2000)); | |
} | |
} | |
} | |
@Override | |
public void onGetNotInCache(String imageUrl, View view) { | |
// TODO Auto-generated method stub | |
if (view != null && view instanceof ImageView) { | |
((ImageView) view).setImageResource(R.drawable.ic_launcher); | |
} | |
} | |
@Override | |
public void onGetFailed(String imageUrl, Bitmap loadedImage, | |
View view, FailedReason failedReason) { | |
// TODO Auto-generated method stub | |
AppLogger.i(new StringBuilder(128).append("get image ") | |
.append(imageUrl).append(" error, failed type is: ") | |
.append(failedReason.getFailedType()) | |
.append(", failed reason is: ") | |
.append(failedReason.getCause().getMessage()) | |
.toString()); | |
} | |
private void setImageScale(String path, ImageView image) { | |
BitmapFactory.Options options = new BitmapFactory.Options(); | |
options.inSampleSize = getImageScale(path); | |
Bitmap bmBitmap = BitmapFactory.decodeFile(path, options); | |
image.setImageBitmap(bmBitmap); | |
} | |
public AlphaAnimation getInAlphaAnimation(long durationMillis) { | |
AlphaAnimation inAlphaAnimation = new AlphaAnimation(0, 1); | |
inAlphaAnimation.setDuration(durationMillis); | |
return inAlphaAnimation; | |
} | |
private int IMAGE_MAX_WIDTH = 480; | |
private int IMAGE_MAX_HEIGHT = 960; | |
private int getImageScale(String image) { | |
// TODO Auto-generated method stub | |
BitmapFactory.Options option = new BitmapFactory.Options(); | |
// allowing the caller to query the bitmap without having to | |
// allocate | |
// the memory for its pixels.表示仅读取图片文件信息而不为图片分配内存 | |
option.inJustDecodeBounds = true; | |
BitmapFactory.decodeFile(image, option); | |
int scale = 1; | |
// 不断缩小 | |
while (option.outWidth / scale >= IMAGE_MAX_WIDTH | |
|| option.outHeight / scale >= IMAGE_MAX_HEIGHT) { | |
scale *= 2; | |
} | |
return scale; | |
} | |
}; | |
// 添加监听 | |
IAMGE_CACHE.setOnImageCallbackListener(imageCallBack); | |
IAMGE_CACHE | |
.setCacheFullRemoveType(new RemoveTypeLastUsedTimeFirst<Bitmap>()); | |
IAMGE_CACHE.setHttpReadTimeOut(10000); | |
IAMGE_CACHE.setOpenWaitingQueue(true); | |
IAMGE_CACHE.setValidTime(-1); | |
/********************************** SD **************************************************************/ | |
// get data from sdcard ,加载本地已经缓存的图片 | |
IAMGE_CACHE | |
.setOnGetDataListener(new OnGetDataListener<String, Bitmap>() { | |
/** | |
* | |
*/ | |
private static final long serialVersionUID = 1L; | |
@Override | |
public CacheObject<Bitmap> onGetData(String key) { | |
// TODO Auto-generated method stub | |
AppLogger.i("path:" + key); | |
if (!FileUtils.isFileExist(key)) | |
return null; | |
// 设置压缩 | |
CompressListener compressListener = IAMGE_CACHE | |
.getCompressListener(); | |
int compressSize = 0; | |
if (compressListener != null) { | |
compressSize = compressListener | |
.getCompressSize(key); | |
} | |
Bitmap bm; | |
if (compressSize > 1) { | |
BitmapFactory.Options bmo = new BitmapFactory.Options(); | |
bmo.inSampleSize = compressSize; | |
bm = BitmapFactory.decodeFile(key, bmo); | |
} else { | |
bm = BitmapFactory.decodeFile(key); | |
} | |
return (bm == null ? null : new CacheObject<Bitmap>(bm)); | |
} | |
}); | |
// 有效解决OOM 问题,将图片压缩 | |
IAMGE_CACHE.setCompressListener(new CompressListener() { | |
@Override | |
public int getCompressSize(String imagePath) { | |
// TODO Auto-generated method stub | |
if (FileUtils.isFileExist(imagePath)) { | |
long fileSize = FileUtils.getFileSize(imagePath) / 1000; | |
/** | |
* if the file is larger than 100k,compress to 1/(n+1) width | |
* and 1/(n+1)height,n=fileSize/100k | |
*/ | |
if (fileSize > 500) { | |
return (int) (fileSize / 500) + 1; | |
} | |
} | |
return 1; | |
} | |
}); | |
} | |
/************************************************************************************************/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment