资料参考来源:
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, Handler
, AsyncTask
, IntentService
, etc.
明白了吧,大概意思就是可以用Handler,AsyncTask,IntentService这些方法。
第二个关键点就是用使用View Holder去holder一个View Objects
在滑动ListView的时候,你可能会频繁地去使用findViewByid(),这就会减缓listView的滑动速度。而且适配器回收或返回一个视图给ListView的时候,仍然需要通过findViewByid()方法去查找和更新list每一行的元素。
A 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();}