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

 

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



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

 

posted @ 2016-08-22 14:15  月是故乡明95  阅读(154)  评论(0编辑  收藏  举报