• 解决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

  • 相关阅读:
    dubbo入门(一)
    java中文件操作《一》
    Unity 游戏框架搭建 2019 (七) 自定义快捷键
    凉鞋:我所理解的框架 【Unity 游戏框架搭建】
    Unity 游戏框架搭建 2019 (六) MenuItem 复用
    Unity 游戏框架搭建 2019 (五) 打开所在文件夹
    Unity 游戏框架搭建 2019 (四) 导出 UnityPackage
    Unity 游戏框架搭建 2019 (三) 生成文件名到剪切板
    Unity 游戏框架搭建 2019 (二) 文本复制到剪切板
    Unity 游戏框架搭建 2019 (一) 简介与第一个示例文件名的生成
  • 原文地址:https://www.cnblogs.com/youngforlife/p/3569722.html
Copyright © 2020-2023  润新知