现在的位置: 首页 > 综合 > 正文

Android GridView视图缓存优化

2018年04月10日 ⁄ 综合 ⁄ 共 6405字 ⁄ 字号 评论关闭

本文提出的优化方法是:在getView()构建一个View列表(List<View>),把最近构建的View存起来,回退时直接从View列表中读取,而不是动态构建。使用这种方法有2个好处:

       1.快速读取过去的Item;

       2.直接保存View而不是Bitmap,避免了ImageView.setImageBitmaps()带来的延时。

       当然坏处就是浪费内存,所以要设定一个上限,超过了就删掉最老的Item。

       “CacheAdapter 缓存50个Item”比ViewHolderAdapter的速度略快,“CacheAdapter 缓存75个Item”依然是最快的。
        总结:“CacheAdapter 缓存50个Item”速度与HolderView略快,读取最近的Item速度最快,缓存的Item越多速度越快。“CacheAdapter 缓存75个Item”占用内存最少,这是由于一部分图片下载失败,保存的Item的图片为空,实际上是缓存越多Item占用的内存越多。

        CacheAdapter.java是实现缓存Item的自定义Adapter,源码如下:

java代码:

  1. /** 
  2. * 使用列表缓存过去的Item 
  3. * @author hellogv 

  4. */ 
  5. public class CacheAdapter extends BaseAdapter { 


  6. public class Item { 
  7. public String itemImageURL; 
  8. public String itemTitle; 
  9. public Item(String itemImageURL, String itemTitle) { 
  10. this.itemImageURL = itemImageURL; 
  11. this.itemTitle = itemTitle; 




  12. private Context mContext; 
  13. private ArrayList<Item> mItems = new ArrayList<Item>(); 
  14. LayoutInflater inflater; 
  15. public CacheAdapter(Context c) { 
  16. mContext = c; 
  17. inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 



  18. public void addItem(String itemImageURL, String itemTitle) { 
  19. mItems.add(new Item(itemImageURL, itemTitle)); 



  20. public int getCount() { 
  21. return mItems.size(); 



  22. public Item getItem(int position) { 
  23. return mItems.get(position); 



  24. public long getItemId(int position) { 
  25. return position; 



  26. List<Integer> lstPosition=new ArrayList<Integer>(); 
  27. List<View> lstView=new ArrayList<View>(); 

  28. List<Integer> lstTimes= new ArrayList<Integer>(); 
  29. long startTime=0; 
  30. public View getView(int position, View convertView, ViewGroup parent) { 
  31. startTime=System.nanoTime(); 
  32. if (lstPosition.contains(position) == false) { 
  33. if(lstPosition.size()>75)//这里设置缓存的Item数量 

  34. lstPosition.remove(0);//删除第一项 
  35. lstView.remove(0);//删除第一项 

  36. convertView = inflater.inflate(R.layout.item, null); 
  37. TextView text = (TextView) convertView.findViewById(R.id.itemText); 
  38. ImageView icon = (ImageView) convertView.findViewById(R.id.itemImage); 
  39. text.setText(mItems.get(position).itemTitle); 
  40. new AsyncLoadImage().execute(new Object[] { icon,mItems.get(position).itemImageURL }); 
  41. lstPosition.add(position);//添加最新项 
  42. lstView.add(convertView);//添加最新项 
  43. } else { 
  44. convertView = lstView.get(lstPosition.indexOf(position)); 

  45. int endTime=(int) (System.nanoTime()-startTime); 
  46. lstTimes.add(endTime); 
  47. if(lstTimes.size()==10) 

  48. int total=0; 
  49. for(int i=0;i<lstTimes.size();i++) 
  50. total=total+lstTimes.get(i); 
  51. Log.e("10个所花的时间:" +total/1000 +" μs", "所用内存:"+Runtime.getRuntime().totalMemory()/1024 +" KB"); 
  52. lstTimes.clear(); 



  53. return convertView; 

  54. /** 
  55. * 异步读取网络图片 
  56. * @author hellogv 
  57. */ 
  58. class AsyncLoadImage extends AsyncTask<Object, Object, Void> { 


  59. @Override 
  60. protected Void doInBackground(Object... params) { 
  61. try { 
  62. ImageView imageView=(ImageView) params[0]; 
  63. String url=(String) params[1]; 
  64. Bitmap bitmap = getBitmapByUrl(url); 


  65. publishProgress(new Object[] {imageView, bitmap}); 
  66. } catch (MalformedURLException e) { 
  67. Log.e("error",e.getMessage()); 
  68. e.printStackTrace(); 
  69. } catch (IOException e) { 
  70. Log.e("error",e.getMessage()); 
  71. e.printStackTrace(); 

  72. return null; 

  73. protected void onProgressUpdate(Object... progress) { 
  74. ImageView imageView = (ImageView) progress[0]; 
  75. imageView.setImageBitmap((Bitmap) progress[1]); 


  76. static public Bitmap getBitmapByUrl(String urlString) 
  77. throws MalformedURLException, IOException { 
  78. URL url = new URL(urlString); 
  79. URLConnection connection = url.openConnection(); 
  80. connection.setConnectTimeout(25000); 
  81. connection.setReadTimeout(90000); 
  82. Bitmap bitmap = BitmapFactory.decodeStream(connection.getInputStream()); 
  83. return bitmap; 

  84. }

复制代码

其中if(lstPosition.size()>75)是设置缓存的Item数量的关键地方,这里缓存75个Item。

        ViewHolderAdapter.java是实现ViewHolder加载Item的自定义Adapter,源码如下:

java代码:

  1. /** 
  2. * 使用ViewHolder加载Item 
  3. * @author hellogv 

  4. */ 
  5. public class ViewHolderAdapter extends BaseAdapter { 
  6. public class Item { 
  7. public String itemImageURL; 
  8. public String itemTitle; 
  9. public Item(String itemImageURL, String itemTitle) { 
  10. this.itemImageURL = itemImageURL; 
  11. this.itemTitle = itemTitle; 




  12. private Context mContext; 
  13. private ArrayList<Item> mItems = new ArrayList<Item>(); 
  14. LayoutInflater inflater; 
  15. public ViewHolderAdapter(Context c) { 
  16. mContext = c; 
  17. inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 



  18. public void addItem(String itemImageURL, String itemTitle) { 
  19. mItems.add(new Item(itemImageURL, itemTitle)); 



  20. public int getCount() { 
  21. return mItems.size(); 



  22. public Item getItem(int position) { 
  23. return mItems.get(position); 



  24. public long getItemId(int position) { 
  25. return position; 



  26. static class ViewHolder { 
  27. TextView text; 
  28. ImageView icon; 



  29. List<Integer> lstTimes= new ArrayList<Integer>(); 
  30. long startTime=0; 
  31. public View getView(int position, View convertView, ViewGroup parent) { 
  32. startTime=System.nanoTime(); 
  33. ViewHolder holder; 
  34. if (convertView == null) { 
  35. convertView = inflater.inflate(R.layout.item, null); 
  36. holder = new ViewHolder(); 
  37. holder.text = (TextView) convertView.findViewById(R.id.itemText); 
  38. holder.icon = (ImageView) convertView.findViewById(R.id.itemImage); 
  39. convertView.setTag(holder); 
  40. } else { 
  41. holder = (ViewHolder) convertView.getTag(); 

  42. holder.text.setText(mItems.get(position).itemTitle); 
  43. new AsyncLoadImage().execute(new Object[]{holder.icon,mItems.get(position).itemImageURL }); 
  44. int endTime=(int) (System.nanoTime()-startTime); 
  45. lstTimes.add(endTime); 
  46. if(lstTimes.size()==10) { 
  47. int total=0; 
  48. for(int i=0;i<lstTimes.size();i++) 
  49. total=total+lstTimes.get(i); 
  50. Log.e("10个所花的时间:" +total/1000 +" μs", 
  51. "所用内存:"+Runtime.getRuntime().totalMemory()/1024 +" KB"); 
  52. lstTimes.clear(); 

  53. return convertView; 

  54. /** 
  55. * 异步读取网络图片 
  56. * @author hellogv 
  57. */ 
  58. class AsyncLoadImage extends AsyncTask<Object, Object, Void> { 


  59. @Override 
  60. protected Void doInBackground(Object... params) { 
  61. try { 
  62. ImageView imageView=(ImageView) params[0]; 
  63. String url=(String) params[1]; 
  64. Bitmap bitmap = CacheAdapter.getBitmapByUrl(url); 
  65. publishProgress(new Object[] {imageView, bitmap}); 
  66. } catch (MalformedURLException e) { 
  67. e.printStackTrace(); 
  68. } catch (IOException e) { 
  69. e.printStackTrace(); 

  70. return null; 

  71. protected void onProgressUpdate(Object... progress) { 
  72. ImageView imageView = (ImageView) progress[0]; 
  73. imageView.setImageBitmap((Bitmap) progress[1]); 




  74. }

复制代码

testPerformance.java是主程序,通过注释符就可以分别测试CacheAdapter与ViewHolderAdapter的性能,源码如下:

java代码:

  1. public class testPerformance extends Activity { 
  2. /** Called when the activity is first created. */ 


  3. @Override 
  4. public void onCreate(Bundle savedInstanceState) { 
  5. super.onCreate(savedInstanceState); 
  6. setContentView(R.layout.main); 
  7. this.setTitle("android平板上的GridView视图缓存优化-----hellogv"); 
  8. GridView gridview = (GridView) findViewById(R.id.gridview); 
  9. CacheAdapter adapter=new CacheAdapter(this); 
  10. // ViewHolderAdapter adapter=new ViewHolderAdapter(this); 
  11. gridview.setAdapter(adapter); 
  12. String urlImage="";//请自己选择网络上的静态图片 
  13. for(int i=0;i<100;i++) 

  14. adapter.addItem(urlImage, "第"+i+"项"); 



  15. }

复制代码


抱歉!评论已关闭.