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

来源:互联网 发布:揭阳华诺网络 编辑:程序博客网 时间:2024/05/19 08:39

资料参考来源:

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 0
原创粉丝点击