zoukankan      html  css  js  c++  java
  • 图片加载AndroidListView异步加载图片

    每日一贴,今天的内容关键字为图片加载

        写这篇文章并不是教大家怎么样用listview异步加载图片

        http://dl.vmall.com/c0qtttyovd

        之前写了一个小的demo,下面是网盘下载的地址

        先说说这篇文章的优点把,开启线程异步加载图片,然后刷新UI表现图片,而且通过弱引用缓存网络加载的图片,节省了再次连接网络的开销。

        这样做无疑是非常可取的方法,但是加载图片时仍然会感觉到轻微的卡屏现象,特别是listview里的item在进行倏地滑动的时候。

        我找了一下原因,可能是在listview倏地滑动屏幕的时候划过的item太多 而且每次调用getView方法后就会异步的在从前某个时间内用handler刷新一下UI,

        如果在同一时间调用handler刷新UI次数多了就会形成这样的卡屏现象。

        后来又一想,其实我们完整没有必要在listview正在滑动的时候去后台加载图片(不管这是图片是在缓存里还是在网络上),这样无疑形成了很大的资源浪费。

        我们只需要在listview滑动停止以后再去加载listview里面表现的几个item里面的图片就好了。

        根据以上想法,我做了一些设计改革:

        1.在adapter 的 getview方法里面启动加载图片的thread,如果listview在滑动则wait

        2.监听listview滑动停止事件,获得listview表现的item的最下面和最下面的序号,并唤醒全部加载图片的thread,判断加载图片的序号是不是是在范围内,如果是则继承加载,如果不是则结束thread

        


        

    部分代码如下:

        

    Java代码   图片和加载
    1. @Override  
    2. public View getView(int position, View convertView, ViewGroup parent)
    3.    {  
    4.     if(convertView == null){  
    5.         convertView = mInflater.inflate(R.layout.book_item_adapter, null);  
    6.     }  
    7.     BookModel model = mModels.get(position);  
    8.     convertView.setTag(position);  
    9.     ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);  
    10.     TextView sItemTitle =  (TextView) convertView.findViewById(R.id.sItemTitle);  
    11.     TextView sItemInfo =  (TextView) convertView.findViewById(R.id.sItemInfo);  
    12.     sItemTitle.setText(model.book_name);  
    13.     sItemInfo.setText(model.out_book_url);  
    14.     iv.setBackgroundResource(R.drawable.rc_item_bg);  
    15.     syncImageLoader.loadImage(position,model.out_book_pic,imageLoadListener);  
    16.     return  convertView;  
    17. }  
    18.   
    19. SyncImageLoader.OnImageLoadListener imageLoadListener = new SyncImageLoader.OnImageLoadListener(){  
    20.   
    21.     @Override  
    22.     public void onImageLoad(Integer t, Drawable drawable) {  
    23.         //BookModel model = (BookModel) getItem(t);  
    24.         View view = mListView.findViewWithTag(t);  
    25.         if(view != null){  
    26.             ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);  
    27.             iv.setBackgroundDrawable(drawable);  
    28.         }  
    29.     }  
    30.     @Override  
    31.     public void onError(Integer t) {  
    32.         BookModel model = (BookModel) getItem(t);  
    33.         View view = mListView.findViewWithTag(model);  
    34.         if(view != null){  
    35.             ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);  
    36.             iv.setBackgroundResource(R.drawable.rc_item_bg);  
    37.         }  
    38.     }  
    39.       
    40. };  
    41.   
    42. public void loadImage(){  
    43.     int start = mListView.getFirstVisiblePosition();  
    44.     int end =mListView.getLastVisiblePosition();  
    45.     if(end >= getCount()){  
    46.         end = getCount() -1;  
    47.     }  
    48.     syncImageLoader.setLoadLimit(start, end);  
    49.     syncImageLoader.unlock();  
    50. }  
    51.   
    52. AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() {  
    53.       
    54.     @Override  
    55.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
    56.         switch (scrollState) {  
    57.             case AbsListView.OnScrollListener.SCROLL_STATE_FLING:  
    58.                 DebugUtil.debug("SCROLL_STATE_FLING");  
    59.                 syncImageLoader.lock();  
    60.                 break;  
    61.             case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:  
    62.                 DebugUtil.debug("SCROLL_STATE_IDLE");  
    63.                 loadImage();  
    64.                 //loadImage();  
    65.                 break;  
    66.             case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:  
    67.                 syncImageLoader.lock();  
    68.                 break;  
    69.   
    70.             default:  
    71.                 break;  
    72.         }  
    73.           
    74.     }  
    75.       
    76.     @Override  
    77.     public void onScroll(AbsListView view, int firstVisibleItem,  
    78.             int visibleItemCount, int totalItemCount) {  
    79.         // TODO Auto-generated method stub  
    80.           
    81.     }  
    82. };  
      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.   
    11. import android.graphics.drawable.Drawable;  
    12. import android.os.Environment;  
    13. import android.os.Handler;  
    14.   
    15. public class SyncImageLoader {  
    16.   
    17.     private Object lock = new Object();  
    18.       
    19.     private boolean mAllowLoad = true;  
    20.       
    21.     private boolean firstLoad = true;  
    22.       
    23.     private int mStartLoadLimit = 0;  
    24.       
    25.     private int mStopLoadLimit = 0;  
    26.       
    27.     final Handler handler = new Handler();  
    28.       
    29.     private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();     
    30.       
    31.     public interface OnImageLoadListener {  
    32.         public void onImageLoad(Integer t, Drawable drawable);  
    33.         public void onError(Integer t);  
    34.     }  
    35.       
    36.     public void setLoadLimit(int startLoadLimit,int stopLoadLimit){  
    37.         if(startLoadLimit > stopLoadLimit){  
    38.             return;  
    39.         }  
    40.         mStartLoadLimit = startLoadLimit;  
    41.         mStopLoadLimit = stopLoadLimit;  
    42.     }  
    43.       
    44.     public void restore(){  
    45.         mAllowLoad = true;  
    46.         firstLoad = true;  
    47.     }  
    48.           
    49.     public void lock(){  
    50.         mAllowLoad = false;  
    51.         firstLoad = false;  
    52.     }  
    53.       
    54.     public void unlock(){  
    55.         mAllowLoad = true;  
    56.         synchronized (lock) {  
    57.             lock.notifyAll();  
    58.         }  
    59.     }  
    60.   
    61.     public void loadImage(Integer t, String imageUrl,  
    62.             OnImageLoadListener listener) {  
    63.         final OnImageLoadListener mListener = listener;  
    64.         final String mImageUrl = imageUrl;  
    65.         final Integer mt = t;  
    66.           
    67.         new Thread(new Runnable() {  
    68.   
    69.             @Override  
    70.             public void run() {  
    71.                 if(!mAllowLoad){  
    72.                     DebugUtil.debug("prepare to load");  
    73.                     synchronized (lock) {  
    74.                         try {  
    75.                             lock.wait();  
    76.                         } catch (InterruptedException e) {  
    77.                             // TODO Auto-generated catch block  
    78.                             e.printStackTrace();  
    79.                         }  
    80.                     }  
    81.                 }  
    82.                   
    83.                 if(mAllowLoad && firstLoad){  
    84.                     loadImage(mImageUrl, mt, mListener);  
    85.                 }  
    86.                   
    87.                 if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit){  
    88.                     loadImage(mImageUrl, mt, mListener);  
    89.                 }  
    90.             }  
    91.   
    92.         }).start();  
    93.     }  
    94.       
    95.     private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener){  
    96.           
    97.         if (imageCache.containsKey(mImageUrl)) {    
    98.             SoftReference<Drawable> softReference = imageCache.get(mImageUrl);    
    99.             final Drawable d = softReference.get();    
    100.             if (d != null) {    
    101.                 handler.post(new Runnable() {  
    102.                     @Override  
    103.                     public void run() {  
    104.                         if(mAllowLoad){  
    105.                             mListener.onImageLoad(mt, d);  
    106.                         }  
    107.                     }  
    108.                 });  
    109.                 return;    
    110.             }    
    111.         }    
    112.         try {  
    113.             final Drawable d = loadImageFromUrl(mImageUrl);  
    114.             if(d != null){  
    115.                 imageCache.put(mImageUrl, new SoftReference<Drawable>(d));  
    116.             }  
    117.             handler.post(new Runnable() {  
    118.                 @Override  
    119.                 public void run() {  
    120.                     if(mAllowLoad){  
    121.                         mListener.onImageLoad(mt, d);  
    122.                     }  
    123.                 }  
    124.             });  
    125.         } catch (IOException e) {  
    126.             handler.post(new Runnable() {  
    127.                 @Override  
    128.                 public void run() {  
    129.                     mListener.onError(mt);  
    130.                 }  
    131.             });  
    132.             e.printStackTrace();  
    133.         }  
    134.     }  
    135.   
    136.     public static Drawable loadImageFromUrl(String url) throws IOException {  
    137.         DebugUtil.debug(url);  
    138.         if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){  
    139.             File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/"+MD5.getMD5(url));  
    140.             if(f.exists()){  
    141.                 FileInputStream fis = new FileInputStream(f);  
    142.                 Drawable d = Drawable.createFromStream(fis, "src");  
    143.                 return d;  
    144.             }  
    145.             URL m = new URL(url);  
    146.             InputStream i = (InputStream) m.getContent();  
    147.             DataInputStream in = new DataInputStream(i);  
    148.             FileOutputStream out = new FileOutputStream(f);  
    149.             byte[] buffer = new byte[1024];  
    150.             int   byteread=0;  
    151.             while ((byteread = in.read(buffer)) != -1) {  
    152.                 out.write(buffer, 0, byteread);  
    153.             }  
    154.             in.close();  
    155.             out.close();  
    156.             Drawable d = Drawable.createFromStream(i, "src");  
    157.             return loadImageFromUrl(url);  
    158.         }else{  
    159.             URL m = new URL(url);  
    160.             InputStream i = (InputStream) m.getContent();  
    161.             Drawable d = Drawable.createFromStream(i, "src");  
    162.             return d;  
    163.         }  
    164.           
    165.     }  
    166. }  

        除了本身已有的弱引用缓存图片,我还添加了当地SD卡缓存图片(这两种缓存方法各有利益,如果图片经常变化提议内存缓存图片,如果是不经常修改的图片提议SD卡缓存)

        参考http://www.iteye.com/topic/1118828文章

    文章结束给大家分享下程序员的一些笑话语录: 程序员喝酒
      我偶尔采用“木马策略”、“交叉测试”,时间不长就开始“频繁分配释放资源”,“cache”也是免不了的了,
      不过我从不搞“轮巡”,也不会“捕获异常”,更不会“程序异常”,因为我有理性
    克制的。  

    --------------------------------- 原创文章 By
    图片和加载
    ---------------------------------

  • 相关阅读:
    redis的两种备份方式
    Vue—事件修饰符
    css3实现颤动的动画
    初学者可能不知道的vue技巧
    使用slot-scope复制vue中slot内容
    pre-commit钩子,代码质量检查
    爬虫可视化点选配置工具之获取鼠标点选元素
    Vue源码探究-事件系统
    使用electron实现百度网盘悬浮窗口功能!
    electron实现qq快捷登录!
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3098874.html
Copyright © 2011-2022 走看看