解决ListView滑动时卡的问题,实现异步加载图片解决

来源:互联网 发布:开淘宝店的创业计划书 编辑:程序博客网 时间:2024/06/05 05:55

ListView是最为常见的空间之一,现在的应用的呈现形式大多数都需要用到ListView来呈现,以列表的方式最直观最便于操作。

那么在使用的过程中大家一定使用adapter适配器来匹配这个ListView,问题就来了,如果直接使用sampleAdapter的话,会出现诸多的问题,诸如滚动的时候很卡,特别是每一行都有头像啊什么的,再加上数据量一大,兼职就卡的不行,那么先来说说解决卡的问题的简单的实现方法吧。

首先需要自己来写一个myAdapter继承与BaseAdapter。

然后最关键的是在getView方法中做到以下几点判断convertView是否为空,这样可以避免每次滚动都去新建,可以节约大量资源,同时对于图片采用开启线程以异步加载的方式来加载它,又可以节约一部分资源,同时,将加载下来的图片缓存到本地,当下一次的时候首先读取本地图片,第一可以节约流量,其次速度非常快(不过服务器图片更新了这个要想好解决方案,不然你本地的图片不会被替换掉)。最后就是在滚动时间的时候让异步加载暂停,等手放开的时候再加载,这样可以保证滚动的超级流畅,不过同时会出现滚动比较大的时候图片都还是空的没有加载的现象,反正自己斟酌优劣吧,代码都有哈!接下来上代码了

首先是主activity

[java] view plaincopy
  1. package com.challen;  
  2.   
  3. import java.util.Vector;  
  4.   
  5. import cindy.android.test.synclistview.R;  
  6. import android.app.Activity;  
  7. import android.content.Context;  
  8. import android.graphics.drawable.Drawable;  
  9. import android.os.Bundle;  
  10. import android.os.Handler;  
  11. import android.os.Message;  
  12. import android.view.LayoutInflater;  
  13. import android.view.View;  
  14. import android.view.ViewGroup;  
  15. import android.widget.AbsListView;  
  16. import android.widget.AdapterView;  
  17. import android.widget.BaseAdapter;  
  18. import android.widget.ImageView;  
  19. import android.widget.ListView;  
  20. import android.widget.TextView;  
  21.   
  22. public class TestListViewActivity extends Activity implements  
  23.         AdapterView.OnItemClickListener {  
  24.   
  25.     ListView viewBookList;  
  26.     BookItemAdapter adapter;  
  27.   
  28.     @Override  
  29.     protected void onCreate(Bundle savedInstanceState) {  
  30.         // TODO Auto-generated method stub  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.main);  
  33.         viewBookList = (ListView) findViewById(R.id.viewBookList);  
  34.   
  35.         adapter = new BookItemAdapter(this, viewBookList);  
  36.   
  37.         viewBookList.setAdapter(adapter);  
  38.         viewBookList.setOnItemClickListener(this);  
  39.         reload();  
  40.     }  
  41.   
  42.     private void reload() {  
  43.         adapter.clean();  
  44.         // loadStateView.startLoad();  
  45.         new Thread(new Runnable() {  
  46.             @Override  
  47.             public void run() {  
  48.                 try {  
  49.                     Thread.sleep(2 * 1000);  
  50.                 } catch (InterruptedException e) {  
  51.                     // TODO Auto-generated catch block  
  52.                     e.printStackTrace();  
  53.                 }  
  54.                 loadDate();  
  55.                 sendMessage(REFRESH_LIST);  
  56.             }  
  57.         }).start();  
  58.     }  
  59.   
  60.     public void loadDate() {  
  61.         for (int i = 0; i < 100; i++) {  
  62.             adapter.addBook("我是challen的测试异步加" + i, "1",  
  63.                     "http://ww1.sinaimg.cn/thumbnail/80ab1ad3gw1dx8tfjvbgdj.jpg");  
  64.   
  65.             adapter.addBook("小美" + i, "2",  
  66.                     "http://ww2.sinaimg.cn/thumbnail/7f9fd9a9jw1dtyrqrh4mjj.jpg");  
  67.   
  68.             adapter.addBook("金总" + i, "3",  
  69.                     "http://ww3.sinaimg.cn/thumbnail/9d57e8e4jw1dx6topumz5j.jpg");  
  70.   
  71.             adapter.addBook("创意铺子" + i, "4",  
  72.                     "http://www.pfwx.com/files/article/image/3/3237/3237s.jpg");  
  73.   
  74.             adapter.addBook("人名日报" + i, "5",  
  75.                     "http://ww2.sinaimg.cn/thumbnail/9263d293jw1dx8snx58s7j.jpg");  
  76.   
  77.             adapter.addBook("名字是乱明的" + i, "6",  
  78.                     "http://tp1.sinaimg.cn/1660452532/50/5646449168/0");  
  79.             adapter.addBook("帅哥即将出现" + i, "7",  
  80.                     "http://p1.qhimg.com/t01a869bb64c7f3d8c6.png");  
  81.             adapter.addBook("注意了哦" + i, "8",  
  82.                     "http://www.baidu.com/img/baidu_jgylogo3.gif");  
  83.             adapter.addBook("来拉" + i, "9",  
  84.                     "http://tp4.sinaimg.cn/2190322767/50/5605436918/1");  
  85.             adapter.addBook("这个就是我啦" + i, "10",  
  86.                     "http://avatar.csdn.net/E/7/2/3_jkingcl.jpg");  
  87.   
  88.         }  
  89.     }  
  90.   
  91.     private static final int REFRESH_LIST = 0x10001;  
  92.     public static final int SHOW_STR_TOAST = 0;  
  93.     public static final int SHOW_RES_TOAST = 1;  
  94.   
  95.     private Handler pichandler = new Handler() {  
  96.         @Override  
  97.         public void handleMessage(Message msg) {  
  98.             if (!Thread.currentThread().isInterrupted()) {  
  99.                 handleOtherMessage(msg.what);  
  100.             }  
  101.         }  
  102.     };  
  103.   
  104.     public void sendMessage(int flag) {  
  105.         pichandler.sendEmptyMessage(flag);  
  106.     }  
  107.   
  108.     protected void handleOtherMessage(int flag) {  
  109.         switch (flag) {  
  110.         case REFRESH_LIST:  
  111.             adapter.notifyDataSetChanged();  
  112.         default:  
  113.             break;  
  114.         }  
  115.     }  
  116.   
  117.     @Override  
  118.     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {  
  119.         // TODO Auto-generated method stub  
  120.   
  121.     }  
  122.   
  123.     public class BookItemAdapter extends BaseAdapter {  
  124.   
  125.         public class BookModel {  
  126.             public String book_id;  
  127.             public String out_book_url;  
  128.             public String author;  
  129.             public String book_state_s;  
  130.             public String leading_role;  
  131.             public String update_time;  
  132.             public String book_name;  
  133.             public String out_book_pic;  
  134.             public String sort_id;  
  135.             public String last_update_section_title;  
  136.             public String last_update_section_url;  
  137.             public String introduction;  
  138.         }  
  139.   
  140.         private LayoutInflater mInflater;  
  141.         private Vector<BookModel> mModels = new Vector<BookModel>();  
  142.         private ListView mListView;  
  143.         SyncImageLoader syncImageLoader;  
  144.   
  145.         public BookItemAdapter(Context context, ListView listView) {  
  146.             mInflater = LayoutInflater.from(context);  
  147.             syncImageLoader = new SyncImageLoader();  
  148.             mListView = listView;  
  149.               
  150.             /* 
  151.              * 
  152.              * 这一句话取消掉注释的话,那么能更加的节省资源,不过体验稍微有点, 
  153.              * 你滑动的时候不会读取图片,当手放开后才开始度图片速度更快,你们可以试一试 
  154.              * */  
  155.               
  156.             // mListView.setOnScrollListener(onScrollListener);  
  157.         }  
  158.   
  159.         public void addBook(String book_name, String author, String out_book_pic) {  
  160.             BookModel model = new BookModel();  
  161.             model.book_name = book_name;  
  162.             model.author = author;  
  163.             model.out_book_pic = out_book_pic;  
  164.             mModels.add(model);  
  165.         }  
  166.   
  167.         public void clean() {  
  168.             mModels.clear();  
  169.         }  
  170.   
  171.         @Override  
  172.         public int getCount() {  
  173.             // TODO Auto-generated method stub  
  174.             return mModels.size();  
  175.         }  
  176.   
  177.         @Override  
  178.         public Object getItem(int position) {  
  179.             if (position >= getCount()) {  
  180.                 return null;  
  181.             }  
  182.             return mModels.get(position);  
  183.         }  
  184.   
  185.         @Override  
  186.         public long getItemId(int position) {  
  187.             // TODO Auto-generated method stub  
  188.             return position;  
  189.         }  
  190.   
  191.         @Override  
  192.         public View getView(int position, View convertView, ViewGroup parent) {  
  193.             if (convertView == null) {  
  194.                 convertView = mInflater.inflate(R.layout.item_adapter,  
  195.                         null);  
  196.             }  
  197.             BookModel model = mModels.get(position);  
  198.             convertView.setTag(position);  
  199.             ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);  
  200.             TextView sItemTitle = (TextView) convertView  
  201.                     .findViewById(R.id.sItemTitle);  
  202.             TextView sItemInfo = (TextView) convertView  
  203.                     .findViewById(R.id.sItemInfo);  
  204.             sItemTitle.setText(model.book_name);  
  205.             sItemInfo.setText(model.out_book_url);  
  206.             // 添加�?��背景在滑动的时�?就会显示背景而不是其他的缓存的照片,用户体验更好  
  207.             iv.setBackgroundResource(R.drawable.rc_item_bg);  
  208.             syncImageLoader.loadImage(position, model.out_book_pic,  
  209.                     imageLoadListener, model.author);  
  210.             return convertView;  
  211.         }  
  212.   
  213.         SyncImageLoader.OnImageLoadListener imageLoadListener = new SyncImageLoader.OnImageLoadListener() {  
  214.   
  215.             @Override  
  216.             public void onImageLoad(Integer t, Drawable drawable) {  
  217.                 // BookModel model = (BookModel) getItem(t);  
  218.                 View view = mListView.findViewWithTag(t);  
  219.                 if (view != null) {  
  220.                     ImageView iv = (ImageView) view  
  221.                             .findViewById(R.id.sItemIcon);  
  222.                     iv.setBackgroundDrawable(drawable);  
  223.                 }  
  224.             }  
  225.   
  226.             @Override  
  227.             public void onError(Integer t) {  
  228.                 BookModel model = (BookModel) getItem(t);  
  229.                 View view = mListView.findViewWithTag(model);  
  230.                 if (view != null) {  
  231.                     ImageView iv = (ImageView) view  
  232.                             .findViewById(R.id.sItemIcon);  
  233.                     iv.setBackgroundResource(R.drawable.rc_item_bg);  
  234.                 }  
  235.             }  
  236.   
  237.         };  
  238.   
  239.         public void loadImage() {  
  240.             int start = mListView.getFirstVisiblePosition();  
  241.             int end = mListView.getLastVisiblePosition();  
  242.             if (end >= getCount()) {  
  243.                 end = getCount() - 1;  
  244.             }  
  245.             syncImageLoader.setLoadLimit(start, end);  
  246.             syncImageLoader.unlock();  
  247.         }  
  248.   
  249.         AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() {  
  250.   
  251.             @Override  
  252.             public void onScrollStateChanged(AbsListView view, int scrollState) {  
  253.                 switch (scrollState) {  
  254.                 case AbsListView.OnScrollListener.SCROLL_STATE_FLING:  
  255.                     syncImageLoader.lock();  
  256.                     break;  
  257.                 case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:  
  258.                     loadImage();  
  259.                     break;  
  260.                 case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:  
  261.                     syncImageLoader.lock();  
  262.                     break;  
  263.   
  264.                 default:  
  265.                     break;  
  266.                 }  
  267.   
  268.             }  
  269.   
  270.             @Override  
  271.             public void onScroll(AbsListView view, int firstVisibleItem,  
  272.                     int visibleItemCount, int totalItemCount) {  
  273.                 // TODO Auto-generated method stub  
  274.   
  275.             }  
  276.         };  
  277.     }  
  278.   
  279. }  


其次是实现异步加载和缓存图片的功能代码loader.java

[java] view plaincopy
  1. package com.challen;  
  2.   
  3. import java.io.DataInputStream;  
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8. import java.io.InputStream;  
  9. import java.lang.ref.SoftReference;  
  10. import java.net.URL;  
  11. import java.util.HashMap;  
  12.   
  13. import android.graphics.drawable.Drawable;  
  14. import android.os.Environment;  
  15. import android.os.Handler;  
  16.   
  17. public class SyncImageLoader {  
  18.   
  19.     private Object lock = new Object();  
  20.       
  21.     private boolean mAllowLoad = true;  
  22.       
  23.     private boolean firstLoad = true;  
  24.       
  25.     private int mStartLoadLimit = 0;  
  26.       
  27.     private int mStopLoadLimit = 0;  
  28.       
  29.     final Handler handler = new Handler();  
  30.       
  31.     private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();     
  32.       
  33.     public interface OnImageLoadListener {  
  34.         public void onImageLoad(Integer t, Drawable drawable);  
  35.         public void onError(Integer t);  
  36.     }  
  37.       
  38.     public void setLoadLimit(int startLoadLimit,int stopLoadLimit){  
  39.         if(startLoadLimit > stopLoadLimit){  
  40.             return;  
  41.         }  
  42.         mStartLoadLimit = startLoadLimit;  
  43.         mStopLoadLimit = stopLoadLimit;  
  44.     }  
  45.       
  46.     public void restore(){  
  47.         mAllowLoad = true;  
  48.         firstLoad = true;  
  49.     }  
  50.           
  51.     public void lock(){  
  52.         mAllowLoad = false;  
  53.         firstLoad = false;  
  54.     }  
  55.       
  56.     public void unlock(){  
  57.         mAllowLoad = true;  
  58.         synchronized (lock) {  
  59.             lock.notifyAll();  
  60.         }  
  61.     }  
  62.   
  63.     public void loadImage(Integer t, String imageUrl,  
  64.             OnImageLoadListener listener,String author1) {  
  65.         final OnImageLoadListener mListener = listener;  
  66.         final String mImageUrl = imageUrl;  
  67.         final Integer mt = t;  
  68.         final String author = author1;  
  69.           
  70.         new Thread(new Runnable() {  
  71.   
  72.             @Override  
  73.             public void run() {  
  74.                 if(!mAllowLoad){  
  75.                     synchronized (lock) {  
  76.                         try {  
  77.                             lock.wait();  
  78.                         } catch (InterruptedException e) {  
  79.                             // TODO Auto-generated catch block  
  80.                             e.printStackTrace();  
  81.                         }  
  82.                     }  
  83.                 }  
  84.                   
  85.                 if(mAllowLoad && firstLoad){  
  86.                     loadImage(mImageUrl, mt, mListener,author);  
  87.                 }  
  88.                   
  89.                 if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit){  
  90.                     loadImage(mImageUrl, mt, mListener,author);  
  91.                 }  
  92.             }  
  93.   
  94.         }).start();  
  95.     }  
  96.       
  97.     private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener,final String author){  
  98.           
  99.         if (imageCache.containsKey(mImageUrl)) {    
  100.             System.out.println("drawable");  
  101.             SoftReference<Drawable> softReference = imageCache.get(mImageUrl);    
  102.             final Drawable d = softReference.get();    
  103.             if (d != null) {    
  104.                 handler.post(new Runnable() {  
  105.                     @Override  
  106.                     public void run() {  
  107.                         if(mAllowLoad){  
  108.                             mListener.onImageLoad(mt, d);  
  109.                         }  
  110.                     }  
  111.                 });  
  112.                 return;    
  113.             }    
  114.         }    
  115.         try {  
  116.             final Drawable d = loadImageFromUrl(mImageUrl,author);  
  117.             if(d != null){  
  118.                 imageCache.put(mImageUrl, new SoftReference<Drawable>(d));  
  119.             }  
  120.             handler.post(new Runnable() {  
  121.                 @Override  
  122.                 public void run() {  
  123.                     if(mAllowLoad){  
  124.                         mListener.onImageLoad(mt, d);  
  125.                     }  
  126.                 }  
  127.             });  
  128.         } catch (IOException e) {  
  129.             handler.post(new Runnable() {  
  130.                 @Override  
  131.                 public void run() {  
  132.                     mListener.onError(mt);  
  133.                 }  
  134.             });  
  135.             e.printStackTrace();  
  136.         }  
  137.     }  
  138.   
  139.     public static Drawable loadImageFromUrl(String url,String author) throws IOException {  
  140.         //是否SD卡可用  
  141.         if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){  
  142.             //检查是或有保存图片的文件夹,没有就穿件一个  
  143.             String FileUrl = Environment.getExternalStorageDirectory()+"/TestSyncListView/";  
  144.             File folder = new File(FileUrl);  
  145.             if(!folder.exists()){  
  146.                 folder.mkdir();  
  147.             }  
  148.             File f = new File(FileUrl+author+".jpg");  
  149.             //SD卡中是否有该文件,有则直接读取返回  
  150.             if(f.exists()){  
  151.                 FileInputStream fis = new FileInputStream(f);  
  152.                 Drawable d = Drawable.createFromStream(fis, "src");  
  153.                 return d;  
  154.             }  
  155.             //没有的话则去连接下载,并写入到SD卡中  
  156.             URL m = new URL(url);  
  157.             InputStream i = (InputStream) m.getContent();  
  158.             DataInputStream in = new DataInputStream(i);  
  159.             FileOutputStream out = new FileOutputStream(f);  
  160.             byte[] buffer = new byte[1024];  
  161.             int   byteread=0;  
  162.             while ((byteread = in.read(buffer)) != -1) {  
  163.                 out.write(buffer, 0, byteread);  
  164.             }  
  165.             in.close();  
  166.             out.close();  
  167.             Drawable d = Drawable.createFromStream(i, "src");  
  168.             return loadImageFromUrl(url,author);  
  169.         }  
  170.         //SD卡不可用则直接加载使用  
  171.         else{  
  172.             URL m = new URL(url);  
  173.             InputStream i = (InputStream) m.getContent();  
  174.             Drawable d = Drawable.createFromStream(i, "src");  
  175.             return d;  
  176.         }  
  177.           
  178.     }  
  179. }  


 

 

最后附上整个测试demo的下载地址,各位可以去下载,然后根据自己的需求加入到自己的项目中,希望可以帮助到大家,大家多多交流哦!

http://download.csdn.net/detail/jkingcl/4726519

0 0
原创粉丝点击