zoukankan      html  css  js  c++  java
  • 解决ListView滑动时卡的问题,实现异步加载图片解决

    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

  • 相关阅读:
    Ubuntu -- 安装、卸载程序的命令
    nodejs基础 -- 多进程
    nodejs基础 -- express框架
    nodejs基础 -- web模块
    nodejs基础 -- 常用工具util
    nodejs基础 -- 全局对象
    nodejs基础 -- 路由
    MVC4中下拉菜单和单选框的简单设计方法
    Uploadify在MVC中使用方法案例(一个视图多次上传单张图片)
    Uploadify在MVC中使用方法案例(上传单张图片)
  • 原文地址:https://www.cnblogs.com/youngforlife/p/3569722.html
Copyright © 2011-2022 走看看