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

资料参考来源:

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代码实例:

public void onCreate() {
     if (DEVELOPER_MODE) {
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .detectDiskWrites()
                 .detectNetwork()   // or .detectAll() for all detectable problems
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());
     }
     super.onCreate();
 }


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

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

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

static class ViewHolder {
  TextView text; 
  TextView timestamp; //时间戳
  ImageView icon;
  ProgressBar progress; //进度条
  int position; 
}

Then populate the ViewHolder and store it inside the layout.

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

ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);//设置一个Tag标签

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

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

ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);//设置一个Tag标签
}else {// 有convertView,按样式,取得不用的布局
	holder = (ViewHolder) convertView.getTag();}





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值