google 最佳实践 - ListView优化 (Making ListView Scrolling Smooth)

来源:互联网 发布:基因表达式编程 编辑:程序博客网 时间:2024/05/29 03:31

资料参考来源:

http://developer.android.com/training/improving-layouts/smooth-scrolling.html

扩展阅读:Why is my list black? An Android optimization

http://www.curious-creature.org/2008/12/22/why-is-my-list-black-an-android-optimization/

http://blog.csdn.net/hhkben/article/details/9955717

我之前写的一篇博客



很多文章写了怎么去优化listView但是没有说明为什么要这样去优化,还有的写了一大推代码,但实际运行情况有不是那么理想。这里说下我自己的理解,争取以最简单的代码实现最好的滑动表现。资料来自android 官方,所以具有一定权威性,希望给大家参考。

------------------------------------------此文更新于2014.1.2-----------------------------------------


1. keep the application’s main thread (the UI thread) free from heavy processing. 

第一个关键点,耗时操作与UI线程分离,使用后台线程去执行这些耗时操作,例如网络请求,数据库请求等,这样主线程就可以专注于UI显示了

小技巧:我们可以用StrictMode这个方法去检测这类的错误 。

StrictMode代码实例:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void onCreate() {  
  2.      if (DEVELOPER_MODE) {  
  3.          StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()  
  4.                  .detectDiskReads()  
  5.                  .detectDiskWrites()  
  6.                  .detectNetwork()   // or .detectAll() for all detectable problems  
  7.                  .penaltyLog()  
  8.                  .build());  
  9.          StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()  
  10.                  .detectLeakedSqlLiteObjects()  
  11.                  .detectLeakedClosableObjects()  
  12.                  .penaltyLog()  
  13.                  .penaltyDeath()  
  14.                  .build());  
  15.      }  
  16.      super.onCreate();  
  17.  }  


那大家的疑问就来了,我们怎么去解决让子线程加载数据这个问题呢?

------------------------官方解答--------------------------------

If you find violations that you feel are problematic, there are a variety of tools to help solve them: threads, HandlerAsyncTaskIntentService, etc.

明白了吧,大概意思就是可以用Handler,AsyncTask,IntentService这些方法。



第二个关键点就是用使用View Holder去holder一个View Objects

在滑动ListView的时候,你可能会频繁地去使用findViewByid(),这就会减缓listView的滑动速度。而且适配器回收或返回一个视图给ListView的时候,仍然需要通过findViewByid()方法去查找和更新list每一行的元素。


ViewHolder object stores each of the component views inside the tag field of the Layout, so you can immediately access them without the need to look them up repeatedly.

意思就是使用ViewHolder可以把每个组件用标签文件的形式储存起来,然后你就可以很快的找到他们,妈妈再也不用担心我们去重复的调用findViewByid()而消耗系统性能了。


那怎么去实现呢? 

 First, you need to create a class to hold your exact set of views. For example:

首先你需要创建一个类去储存你的view

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. static class ViewHolder {  
  2.   TextView text;   
  3.   TextView timestamp; //时间戳  
  4.   ImageView icon;  
  5.   ProgressBar progress; //进度条  
  6.   int position;   
  7. }  

Then populate the ViewHolder and store it inside the layout.

然后填充ViewHolder并将其存储在布局。最后给他设一个标签Tag,以后我们就可以通过这个Tag去查找这个View

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. ViewHolder holder = new ViewHolder();  
  2. holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);  
  3. holder.text = (TextView) convertView.findViewById(R.id.listitem_text);  
  4. holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);  
  5. holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);  
  6. convertView.setTag(holder);//设置一个Tag标签  

现在您可以很容易地访问每个视图不需要查找,节省宝贵的处理器周期。

3,第三个关键点就是要重用列表中行在每次创建一个ViewHolder()之前先判断一下当前position下的view是否为空!优化第二的提到的代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. ViewHolder holder = null;  
  2. if (convertView == null) {  
  3. holder = new ViewHolder();  
  4. holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);  
  5. holder.text = (TextView) convertView.findViewById(R.id.listitem_text);  
  6. holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);  
  7. holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);  
  8. convertView.setTag(holder);//设置一个Tag标签  
  9. }else {// 有convertView,按样式,取得不用的布局  
  10.     holder = (ViewHolder) convertView.getTag();}  
0 0
原创粉丝点击