转:Android ListView 异步加载图片
http://www.iteye.com/topic/1118828
http://www.iteye.com/topic/1127914
这样做无疑是非常可取的方法,但是加载图片时仍然会感觉到轻微的卡屏现象,特别是listview里的item在进行快速滑动的时候。
如果在同一时间调用handler刷新UI次数多了就会造成这样的卡屏现象。
我们只需要在listview滑动停止之后再去加载listview里面显示的几个item里面的图片就好了。
1.在adapter 的 getview方法里面启动加载图片的thread,如果listview在滑动则wait
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = mInflater.inflate(R.layout.book_item_adapter, null);
}
BookModel model = mModels.get(position);
convertView.setTag(position);
ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);
TextView sItemTitle = (TextView) convertView.findViewById(R.id.sItemTitle);
TextView sItemInfo = (TextView) convertView.findViewById(R.id.sItemInfo);
sItemTitle.setText(model.book_name);
sItemInfo.setText(model.out_book_url);
iv.setBackgroundResource(R.drawable.rc_item_bg);
syncImageLoader.loadImage(position,model.out_book_pic,imageLoadListener);
return convertView;
}
SyncImageLoader.OnImageLoadListener imageLoadListener = new SyncImageLoader.OnImageLoadListener(){
@Override
public void onImageLoad(Integer t, Drawable drawable) {
//BookModel model = (BookModel) getItem(t);
View view = mListView.findViewWithTag(t);
if(view != null){
ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
iv.setBackgroundDrawable(drawable);
}
}
@Override
public void onError(Integer t) {
BookModel model = (BookModel) getItem(t);
View view = mListView.findViewWithTag(model);
if(view != null){
ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
iv.setBackgroundResource(R.drawable.rc_item_bg);
}
}
};
public void loadImage(){
int start = mListView.getFirstVisiblePosition();
int end =mListView.getLastVisiblePosition();
if(end >= getCount()){
end = getCount() -1;
}
syncImageLoader.setLoadLimit(start, end);
syncImageLoader.unlock();
}
AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
DebugUtil.debug("SCROLL_STATE_FLING");
syncImageLoader.lock();
break;
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
DebugUtil.debug("SCROLL_STATE_IDLE");
loadImage();
//loadImage();
break;
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
syncImageLoader.lock();
break;
default:
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
};
package cindy.android.test.synclistview;
Syncimageloader代码
- import java.io.DataInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.ref.SoftReference;
- import java.net.URL;
- import java.util.HashMap;
- import android.graphics.drawable.Drawable;
- import android.os.Environment;
- import android.os.Handler;
- public class SyncImageLoader {
- private Object lock = new Object();
- private boolean mAllowLoad = true;
- private boolean firstLoad = true;
- private int mStartLoadLimit = 0;
- private int mStopLoadLimit = 0;
- final Handler handler = new Handler();
- private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
- public interface OnImageLoadListener {
- public void onImageLoad(Integer t, Drawable drawable);
- public void onError(Integer t);
- }
- public void setLoadLimit(int startLoadLimit,int stopLoadLimit){
- if(startLoadLimit > stopLoadLimit){
- return;
- }
- mStartLoadLimit = startLoadLimit;
- mStopLoadLimit = stopLoadLimit;
- }
- public void restore(){
- mAllowLoad = true;
- firstLoad = true;
- }
- public void lock(){
- mAllowLoad = false;
- firstLoad = false;
- }
- public void unlock(){
- mAllowLoad = true;
- synchronized (lock) {
- lock.notifyAll();
- }
- }
- public void loadImage(Integer t, String imageUrl,
- OnImageLoadListener listener) {
- final OnImageLoadListener mListener = listener;
- final String mImageUrl = imageUrl;
- final Integer mt = t;
- new Thread(new Runnable() {
- @Override
- public void run() {
- if(!mAllowLoad){
- DebugUtil.debug("prepare to load");
- synchronized (lock) {
- try {
- lock.wait();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- if(mAllowLoad && firstLoad){
- loadImage(mImageUrl, mt, mListener);
- }
- if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit){
- loadImage(mImageUrl, mt, mListener);
- }
- }
- }).start();
- }
- private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener){
- if (imageCache.containsKey(mImageUrl)) {
- SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
- final Drawable d = softReference.get();
- if (d != null) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- if(mAllowLoad){
- mListener.onImageLoad(mt, d);
- }
- }
- });
- return;
- }
- }
- try {
- final Drawable d = loadImageFromUrl(mImageUrl);
- if(d != null){
- imageCache.put(mImageUrl, new SoftReference<Drawable>(d));
- }
- handler.post(new Runnable() {
- @Override
- public void run() {
- if(mAllowLoad){
- mListener.onImageLoad(mt, d);
- }
- }
- });
- } catch (IOException e) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- mListener.onError(mt);
- }
- });
- e.printStackTrace();
- }
- }
- public static Drawable loadImageFromUrl(String url) throws IOException {
- DebugUtil.debug(url);
- if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
- File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/"+MD5.getMD5(url));
- if(f.exists()){
- FileInputStream fis = new FileInputStream(f);
- Drawable d = Drawable.createFromStream(fis, "src");
- return d;
- }
- URL m = new URL(url);
- InputStream i = (InputStream) m.getContent();
- DataInputStream in = new DataInputStream(i);
- FileOutputStream out = new FileOutputStream(f);
- byte[] buffer = new byte[1024];
- int byteread=0;
- while ((byteread = in.read(buffer)) != -1) {
- out.write(buffer, 0, byteread);
- }
- in.close();
- out.close();
- Drawable d = Drawable.createFromStream(i, "src");
- return loadImageFromUrl(url);
- }else{
- URL m = new URL(url);
- InputStream i = (InputStream) m.getContent();
- Drawable d = Drawable.createFromStream(i, "src");
- return d;
- }
- }
- }

TestSyncListView.rar (147.8
KB)
其实改动不大,就是把之前的new Thread改成了 Handler Looper Thread的模式,这样在第一次滑动的时候就进入了wait状态,又因为handler里面的runnable是队列执行的,所以handler一直在添加的runnable也在等待,这样就避免了多次new
thread的问题,从头到尾就只有一个thread,别的不多说,看修改后的代码。
Runinotherthread代码
import android.os.Handler;
import android.os.Looper;
import android.os.Message; public class RunInOtherThread {
private static final String LOG_TAG = "RunInOtherThread"; private LooperThread localThread = new LooperThread(); private boolean isRunning = true; public Handler getHandler(){
return localThread.getHandler();
} private class LooperThread extends Thread {
private Handler mHandler; public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
onReceiveMessage(msg.what);
}
};
Looper.loop();
} Handler getHandler(){
return mHandler;
} } public void start(){
localThread.start();
} public void quit(){
localThread.getHandler().getLooper().quit();
} public void sendMessage(int what){
getHandler().sendEmptyMessage(what);
} public Thread getThread(){
return localThread;
} public void onReceiveMessage(int what){}; } Syncimageloader代码 import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap; import cindy.android.debug.DebugUtil; import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.os.Handler; public class SyncImageLoader { private Object lock = new Object(); private boolean mAllowLoad = true; private boolean firstLoad = true; private int mStartLoadLimit = 0; private int mStopLoadLimit = 0; final Handler handler = new Handler(); private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>(); RunInOtherThread runInOutherThread; public SyncImageLoader() {
super();
runInOutherThread = new RunInOtherThread();
runInOutherThread.start();
} public interface OnImageLoadListener {
public void onImageLoad(Integer t, Drawable drawable); public void onError(Integer t);
} public void setLoadLimit(int startLoadLimit, int stopLoadLimit) {
if (startLoadLimit > stopLoadLimit) {
return;
}
mStartLoadLimit = startLoadLimit;
mStopLoadLimit = stopLoadLimit;
} public void restore() {
mAllowLoad = true;
firstLoad = true;
} public void lock() {
mAllowLoad = false;
firstLoad = false;
} public void unlock() {
mAllowLoad = true;
synchronized (lock) {
lock.notifyAll();
}
} public void loadImage(Integer t, String imageUrl,
OnImageLoadListener listener) {
final OnImageLoadListener mListener = listener;
final String mImageUrl = imageUrl;
final Integer mt = t; runInOutherThread.getHandler().post(new Runnable() { @Override
public void run() {
if (!mAllowLoad) {
synchronized (lock) {
try {
DebugUtil.debug("wait start.....");
lock.wait();
DebugUtil.debug("wait end.....");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} if (mAllowLoad && firstLoad) {
loadImage(mImageUrl, mt, mListener);
} if (mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit) {
loadImage(mImageUrl, mt, mListener);
}
} });
} private void loadImage(final String mImageUrl, final Integer mt,
final OnImageLoadListener mListener) { if (imageCache.containsKey(mImageUrl)) {
SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
final Drawable d = softReference.get();
if (d != null) {
handler.post(new Runnable() {
@Override
public void run() {
if (mAllowLoad) {
mListener.onImageLoad(mt, d);
}
}
});
return;
}
}
try {
final Drawable d = loadImageFromUrl(mImageUrl);
if (d != null) {
imageCache.put(mImageUrl, new SoftReference<Drawable>(d));
}
handler.post(new Runnable() {
@Override
public void run() {
if (mAllowLoad) {
mListener.onImageLoad(mt, d);
}
}
});
} catch (IOException e) {
handler.post(new Runnable() {
@Override
public void run() {
mListener.onError(mt);
}
});
e.printStackTrace();
}
} public static Drawable loadImageFromUrl(String url) throws IOException {
//DebugUtil.debug(url);
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File f = new File(Environment.getExternalStorageDirectory()
+ "/TestSyncListView/" + MD5.getMD5(url));
if (f.exists()) {
FileInputStream fis = new FileInputStream(f);
Drawable d = Drawable.createFromStream(fis, "src");
return d;
}
URL m = new URL(url);
InputStream i = (InputStream) m.getContent();
DataInputStream in = new DataInputStream(i);
FileOutputStream out = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int byteread = 0;
while ((byteread = in.read(buffer)) != -1) {
out.write(buffer, 0, byteread);
}
in.close();
out.close();
Drawable d = Drawable.createFromStream(i, "src");
return loadImageFromUrl(url);
} else {
URL m = new URL(url);
InputStream i = (InputStream) m.getContent();
Drawable d = Drawable.createFromStream(i, "src");
return d;
} }
}
转:Android ListView 异步加载图片的更多相关文章
- 又优化了一下 Android ListView 异步加载图片
写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看 ...
- android listview 异步加载图片并防止错位
网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertVie ...
- android ListView异步加载图片(双缓存)
首先声明,参考博客地址:http://www.iteye.com/topic/685986 对于ListView,相信很多人都很熟悉,因为确实太常见了,所以,做的用户体验更好,就成了我们的追求... ...
- Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法
Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...
- listview异步加载图片并防止错位
android listview 异步加载图片并防止错位 网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 conver ...
- Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案
我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...
- Android 实现ListView异步加载图片
ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...
- ListView异步加载图片,完美实现图文混排
昨天参加一个面试,面试官让当场写一个类似于新闻列表的页面,文本数据和图片都从网络上获取,想起我还没写过ListView异步加载图片并实现图文混排效果的文章,so,今天就来写一下,介绍一下经验. Lis ...
- ListView异步加载图片
ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...
随机推荐
- linux 安装nginx yum
本分类下有一个环境一键安装.那这背后发生了什么呢?咱们手动使用源码进行安装.1.首先保证有一个能联网的centos.2.百度 ningx 官网 点download http://nginx.or ...
- JDK学习---深入理解java中的String
本文参考资料: 1.<深入理解jvm虚拟机> 2.<大话数据结构>.<大话设计模式> 3.http://www.cnblogs.com/ITtangtang/p/3 ...
- python 函数复习
# 函数 # 可读性强 复用性强 # def 函数名(): # 函数体 #return 返回值 # 所有的函数 只定义不调用就一定不执行 #先定义后调用 #函数名() #不接收返回值 #返回值 = 函 ...
- C# 输出结果有System.Byte[]
byte[]类型直接输出或者调用ToString函数都会出现这个结果. 需要执行: byte[] a=new byte[10]; string text = "";for (int ...
- 理解canvas路径
canvas路径和ps里面的路径差不多,在进行图形绘制时,先绘制出来图形的路径,然后再描边或者填充. canvas路径还有子路径的概念,在某一时刻,canvas之中只能有一条路径存在,Canvas规范 ...
- JVM——九大工具助你玩转Java性能优化
本文转载自 http://www.importnew.com/12324.html 本文由 ImportNew - 陈 晓舜 翻译自 idrsolutions.欢迎加入翻译小组.转载请参见文章末尾的要 ...
- [bzoj2932][POI1999]树的染色问题
被百度搜到的题解(论文?)坑了. 写的那玩意好像石乐志... Description 一棵二叉树采用以下规则描述: 1.如果一个节点度数为0,则仅用一个元素“0”来描述它. 2.如果一个节点度数为1, ...
- 110Balanced Binary Tree
问题:判断二叉树是否为平衡二叉树分析:树上的任意结点的左右子树高度差不超过1,则为平衡二叉树. 搜索递归,记录i结点的左子树高度h1和右子树高度h2,则i结点的高度为max(h1,h2 ...
- 内存泄漏分析 mat 使用 activity泄漏
https://github.com/square/leakcanary square 公司出品 mat 下载地址: http://pan.baidu.com/s/1kVPoIxx 两天,一个内存泄漏 ...
- Android Studio自定义模板代码
http://blog.csdn.net/h183288132/article/details/51916399 生成模板看上面这个博客就可以了,不再重复制造轮子. 不过需要补充的是: 还应该有下面的 ...