• 转: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;  
                }  
          
            }  
        } 
    
  • 相关阅读:
    软阴影的实现(转帖)
    卡巴斯基:警惕IE拦截器恶意推广导航网站 狼人:
    安全问题拷问着电子支付第三方未来 狼人:
    微软警告:泄露的Office 2010预览版或含病毒 狼人:
    《越狱》完结 米帅迷应小心纹身网站挂马 狼人:
    赛门铁克和McAfee:目标锁定iPhone! 狼人:
    McAfee将与EMC合作推出在线PC备份服务 狼人:
    恶意软件分析师:面临社交网络威胁的用户已10亿 狼人:
    Mac OS X现漏洞 苹果称是Java导致恶意攻击 狼人:
    暴风影音声明:DNS服务器才是故障源头 狼人:
  • 原文地址:https://www.cnblogs.com/1995hxt/p/5795404.html
Copyright © 2020-2023  润新知