`
dawuafang
  • 浏览: 1104103 次
文章分类
社区版块
存档分类
最新评论

Android之ListView优化(使用Lrucache,图片滑动时使用默认图片,停止时加载)

 
阅读更多

注意:LruCache是有版本限制的,低版本的sdk需要在libs文件夹添加相应的support-4v文件。
本文改造的大部分是参考http://www.iteye.com/topic/1118828,感谢。
不废话直接上工程代码,内有关键注释,项目就不上传了,自己对照着上面网址改呗。


首先是Application文件,负责创建图片存储文件夹:

复制代码
public class MyApp extends Application{
    @Override
    public void onCreate() {
        super.onCreate();
        File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/pic/");
        if (!f.exists()) {
            f.mkdirs();
        }
    }
}
复制代码


图像读取工具类:

?
publicclassSyncImageLoaderUtil {
privateObject lock = newObject();
privatebooleanmAllowLoad = true;
privatebooleanfirstLoad = true;
privateintmStartLoadLimit = 0;
privateintmStopLoadLimit = 0;
finalHandler handler = newHandler();
// private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
privateLruCache<String,Bitmap> mMemoryCache;
RunInOtherThread runInOutherThread;
publicSyncImageLoaderUtil(Context context) {
super();
intmemClass = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
intcacheSize = 1024* 1024*memClass / 8;
mMemoryCache = newLruCache<String, Bitmap>(cacheSize){
@Override
protectedintsizeOf(String key, Bitmap value) {
// TODO Auto-generated method stub
returnvalue.getRowBytes();
}
};
runInOutherThread = newRunInOtherThread();
runInOutherThread.start();
}
publicinterfaceOnImageLoadListener {
publicvoidonImageLoad(Integer t, Drawable drawable);
publicvoidonError(Integer t);
}
publicvoidsetLoadLimit(intstartLoadLimit, intstopLoadLimit) {
if(startLoadLimit > stopLoadLimit) {
// LogUtil.i("test", startLoadLimit+"--错误---"+stopLoadLimit);
return;
}
mStartLoadLimit = startLoadLimit;
mStopLoadLimit = stopLoadLimit;
}
publicvoidrestore() {
mAllowLoad = true;
firstLoad = true;
}
publicvoidlock() {
mAllowLoad = false;
firstLoad = false;
}
publicvoidunlock() {
mAllowLoad = true;
synchronized(lock) {
lock.notifyAll();
}
}
publicvoidloadImage(Integer t, String imageUrl,
OnImageLoadListener listener) {
finalOnImageLoadListener mListener = listener;
finalString mImageUrl = imageUrl;
finalInteger mt = t;
runInOutherThread.getHandler().post(newRunnable() {
@Override
publicvoidrun() {
if(!mAllowLoad) {
synchronized(lock) {
try{
lock.wait();
} catch(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if(mAllowLoad && firstLoad) {
loadImage(mImageUrl, mt, mListener);
}
// LogUtil.e("test", "原始开始:"+mStartLoadLimit+"原始当前位置:"+mt+"原始结束:"+mStopLoadLimit);
if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit) {
// LogUtil.e("test", "开始:"+mStartLoadLimit+"当前位置:"+mt+"结束:"+mStopLoadLimit);
loadImage(mImageUrl, mt, mListener);
}
}
});
}
privatevoidloadImage(finalString mImageUrl, finalInteger mt,
finalOnImageLoadListener mListener) {
if(mImageUrl!=null&& mMemoryCache.get(mImageUrl)!=null) {
// SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
finalDrawable d = newBitmapDrawable(mMemoryCache.get(mImageUrl));
// LogUtil.d("ppp", "drawable:"+d);
if(d != null) {
handler.post(newRunnable() {
@Override
publicvoidrun() {
if(mAllowLoad) {
mListener.onImageLoad(mt, d);
}
}
});
return;
}
}
try{
finalDrawable d = loadImageFromUrl(mImageUrl);
if(d != null) {
mMemoryCache.put(mImageUrl, ((BitmapDrawable)d).getBitmap());
}
handler.post(newRunnable() {
@Override
publicvoidrun() {
if(mAllowLoad) {
mListener.onImageLoad(mt, d);
}
}
});
} catch(IOException e) {
handler.post(newRunnable() {
@Override
publicvoidrun() {
mListener.onError(mt);
}
});
e.printStackTrace();
}
}
publicstaticDrawable loadImageFromUrl(String url) throwsIOException {
//DebugUtil.debug(url);
if(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File f = newFile(Environment.getExternalStorageDirectory()
+ "/Weiyu/pic/"+ MD5Util.getMD5(url.getBytes()));
if(f.exists()) {
FileInputStream fis = newFileInputStream(f);
Drawable d = Drawable.createFromStream(fis, "src");
returnd;
}
URL m = newURL(url);
InputStream i = (InputStream) m.getContent();
DataInputStream in = newDataInputStream(i);
FileOutputStream out = newFileOutputStream(f);
byte[] buffer = newbyte[1024];
intbyteread = 0;
while((byteread = in.read(buffer)) != -1) {
out.write(buffer, 0, byteread);
}
in.close();
out.close();
returnloadImageFromUrl(url);
} else{
URL m = newURL(url);
InputStream i = (InputStream) m.getContent();
Drawable d = Drawable.createFromStream(i, "src");
returnd;
}
}
}

  
线程辅助类:

?
publicclassRunInOtherThread {
privatestaticfinalString LOG_TAG = "RunInOtherThread";
privateLooperThread localThread = newLooperThread();
privatebooleanisRunning = true;
publicHandler getHandler(){
returnlocalThread.getHandler();
}
privateclassLooperThread extendsThread {
privateHandler mHandler;
publicvoidrun() {
Looper.prepare();
mHandler = newHandler() {
publicvoidhandleMessage(Message msg) {
onReceiveMessage(msg.what);
}
};
Looper.loop();
}
Handler getHandler(){
returnmHandler;
}
}
publicvoidstart(){
localThread.start();
}
publicvoidquit(){
localThread.getHandler().getLooper().quit();
}
publicvoidsendMessage(intwhat){
getHandler().sendEmptyMessage(what);
}
publicThread getThread(){
returnlocalThread;
}
publicvoidonReceiveMessage(intwhat){};
}

  
使用类:

?
// 实例化工具类
SyncImageLoaderUtil syncImageLoader = newSyncImageLoaderUtil(mContext);
syncImageLoader.loadImage(position, model.mPic, imageLoadListener);//应用接口:参数一是加载图片的位置;参数二是加载的ImageView;参数三是回调接口
// map保存的键是位置,值是listview对应位置的布局
HashMap map = newHashMap();
map.put(position, convertView);
SyncImageLoaderUtil.OnImageLoadListener imageLoadListener = newSyncImageLoaderUtil.OnImageLoadListener() {
@Override
publicvoidonImageLoad(Integer t, Drawable drawable) {
View view = (View) map.get(t);
if(view != null) {
ImageView iv = (ImageView) view.findViewById(R.id.image);
iv.setBackgroundDrawable(drawable);
}
}
@Override
publicvoidonError(Integer t) {
// 图片加载失败
// 取得listview对应的位置的行的内容布局
MusicModel model = (MusicModel) getItem(t);
View view = mListView.findViewWithTag(model);
if(view != null) {
ImageView iv = (ImageView) view.findViewById(R.id.image);
iv.setBackgroundResource(R.drawable.img_pic);
}
}
};
// 实现类而且需要实现OnScrollListener接口
publicvoidloadImage() {
// 不要在这里使用listview的getFirstVisiblePosition方法,位置不准
if(end >= getCount()) {
end = getCount() - 1;
}
syncImageLoader.setLoadLimit(start, end);
syncImageLoader.unlock();
}
@Override
publicvoidonScrollStateChanged(AbsListView view, intscrollState) {
// TODO Auto-generated method stub
if(lodingView) {
switch(scrollState) {
caseAbsListView.OnScrollListener.SCROLL_STATE_FLING:
syncImageLoader.lock();
break;
caseAbsListView.OnScrollListener.SCROLL_STATE_IDLE:
loadImage();
break;
caseAbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
syncImageLoader.lock();
break;
default:
break;
}
}
}
@Override
publicvoidonScroll(AbsListView view, intfirstVisibleItem,
intvisibleItemCount, inttotalItemCount) {
// 在这里取得的位置较准确,不过也会出现特殊的奇疤机型是不行的
// start与end是定义的变量
start = firstVisibleItem;
end = firstVisibleItem + visibleItemCount;
if(firstVisibleItem != 0) {
// lodingView是控制变量,用来控制第一次进来视图加载读取图片
lodingView = true;
} else{
lodingView = false;
loadImage();
}
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics