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代码

  1. import java.io.DataInputStream;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.lang.ref.SoftReference;
  8. import java.net.URL;
  9. import java.util.HashMap;
  10. import android.graphics.drawable.Drawable;
  11. import android.os.Environment;
  12. import android.os.Handler;
  13. public class SyncImageLoader {
  14. private Object lock = new Object();
  15. private boolean mAllowLoad = true;
  16. private boolean firstLoad = true;
  17. private int mStartLoadLimit = 0;
  18. private int mStopLoadLimit = 0;
  19. final Handler handler = new Handler();
  20. private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
  21. public interface OnImageLoadListener {
  22. public void onImageLoad(Integer t, Drawable drawable);
  23. public void onError(Integer t);
  24. }
  25. public void setLoadLimit(int startLoadLimit,int stopLoadLimit){
  26. if(startLoadLimit > stopLoadLimit){
  27. return;
  28. }
  29. mStartLoadLimit = startLoadLimit;
  30. mStopLoadLimit = stopLoadLimit;
  31. }
  32. public void restore(){
  33. mAllowLoad = true;
  34. firstLoad = true;
  35. }
  36. public void lock(){
  37. mAllowLoad = false;
  38. firstLoad = false;
  39. }
  40. public void unlock(){
  41. mAllowLoad = true;
  42. synchronized (lock) {
  43. lock.notifyAll();
  44. }
  45. }
  46. public void loadImage(Integer t, String imageUrl,
  47. OnImageLoadListener listener) {
  48. final OnImageLoadListener mListener = listener;
  49. final String mImageUrl = imageUrl;
  50. final Integer mt = t;
  51. new Thread(new Runnable() {
  52. @Override
  53. public void run() {
  54. if(!mAllowLoad){
  55. DebugUtil.debug("prepare to load");
  56. synchronized (lock) {
  57. try {
  58. lock.wait();
  59. } catch (InterruptedException e) {
  60. // TODO Auto-generated catch block
  61. e.printStackTrace();
  62. }
  63. }
  64. }
  65. if(mAllowLoad && firstLoad){
  66. loadImage(mImageUrl, mt, mListener);
  67. }
  68. if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit){
  69. loadImage(mImageUrl, mt, mListener);
  70. }
  71. }
  72. }).start();
  73. }
  74. private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener){
  75. if (imageCache.containsKey(mImageUrl)) {
  76. SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
  77. final Drawable d = softReference.get();
  78. if (d != null) {
  79. handler.post(new Runnable() {
  80. @Override
  81. public void run() {
  82. if(mAllowLoad){
  83. mListener.onImageLoad(mt, d);
  84. }
  85. }
  86. });
  87. return;
  88. }
  89. }
  90. try {
  91. final Drawable d = loadImageFromUrl(mImageUrl);
  92. if(d != null){
  93. imageCache.put(mImageUrl, new SoftReference<Drawable>(d));
  94. }
  95. handler.post(new Runnable() {
  96. @Override
  97. public void run() {
  98. if(mAllowLoad){
  99. mListener.onImageLoad(mt, d);
  100. }
  101. }
  102. });
  103. } catch (IOException e) {
  104. handler.post(new Runnable() {
  105. @Override
  106. public void run() {
  107. mListener.onError(mt);
  108. }
  109. });
  110. e.printStackTrace();
  111. }
  112. }
  113. public static Drawable loadImageFromUrl(String url) throws IOException {
  114. DebugUtil.debug(url);
  115. if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
  116. File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/"+MD5.getMD5(url));
  117. if(f.exists()){
  118. FileInputStream fis = new FileInputStream(f);
  119. Drawable d = Drawable.createFromStream(fis, "src");
  120. return d;
  121. }
  122. URL m = new URL(url);
  123. InputStream i = (InputStream) m.getContent();
  124. DataInputStream in = new DataInputStream(i);
  125. FileOutputStream out = new FileOutputStream(f);
  126. byte[] buffer = new byte[1024];
  127. int   byteread=0;
  128. while ((byteread = in.read(buffer)) != -1) {
  129. out.write(buffer, 0, byteread);
  130. }
  131. in.close();
  132. out.close();
  133. Drawable d = Drawable.createFromStream(i, "src");
  134. return loadImageFromUrl(url);
  135. }else{
  136. URL m = new URL(url);
  137. InputStream i = (InputStream) m.getContent();
  138. Drawable d = Drawable.createFromStream(i, "src");
  139. return d;
  140. }
  141. }
  142. }

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;
} }
}

最新文章

  1. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]
  2. Oracle逻辑结构(TableSpace→Segment→Extent→Block)
  3. linux系统编程之I/O内核数据结构
  4. .Net Request.Form含有危险字符的处理办法
  5. mvc正则@符号js报错解决办法
  6. mysql,sql server,oracle 唯一索引字段是否允许出现多个 null 值?
  7. CSS 实现加载动画之七-彩环旋转
  8. 在虚拟机上安装Ubutu完成后卡在VM Tool的安装上
  9. 黄聪:HtmlAgilityPack,C#实用的HTML解析类 ---- HtmlNode类
  10. POJ 2774 Long Long Message(后缀数组)
  11. 2006 ACM Northwestern European Programming Contest C题(二分求最大)
  12. LCA-倍增法(在线)O(nlogn)-O(logn)
  13. PowerPoint实用知识
  14. stm之SPI通信协议
  15. powerdesigner 不能自动生成注释的解决方法(三步解决)
  16. django ORM多对多操作
  17. Javascript定义变量
  18. javascript篇-typeof,instanceof,constructor,toString判断数据类型的用法和区别
  19. Shell - 简明Shell入门04 - 判断语句(If)
  20. Py2exe——将python程序变成windows下可执行的exe

热门文章

  1. dts--framework(二)
  2. 008---Django的模版层
  3. 005--Django2.0的路由层
  4. 基于itchat定制聊天机器人
  5. 关于C、内存、栈的一些杂谈
  6. 5,MongoDB 之 &quot;$&quot; 的奇妙用法
  7. 关于IAR软件的Go to Definition of功能问题的解决方法
  8. Trident学习笔记(一)
  9. HNOI2018 摸鱼记
  10. css一些事儿