Android性能优化系列---Improving Layout Performance(四)
Making ListView Scrolling Smooth
让ListView平滑滚动的关键在于将程序的主线程(UI线程)从大量的处理中解脱出来。要要保证用单独的线程来进行磁盘,网络或SQL操作。想要测试你的程序的状态, 你可以开启StrictMode。
Use a Background Thread
使用后台线程(“工作线程”)可移除主线程中的压力,这样可以使得UI线程可以专注于描绘UI。大多数时候,AsycnTask实现了一种简单的把需要做的事情与main thread分离的方法。AsyncTask自动将所有execute()请求排成队列并按顺序执行他们。这种行为对一个特定进程来说是全局性的,这意味着你不必担心创建自己的线程池。
下方所示的简单代码中,利用AsyncTask在后台线程中加载图像,然后一旦完成便更新UI。当图片正在加载时可以显示一个Spinner进度条来代替正在加载的图像。
// Using an AsyncTask to load the slow images in a background thread
new AsyncTask<ViewHolder, Void, Bitmap>() {
private ViewHolder v;
@Override
protected Bitmap doInBackground(ViewHolder... params) {
v = params[0];
return mFakeImageLoader.getImage();
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (v.position == position) {
// If this item hasn't been recycled already, hide the
// progress and set and show the image
v.progress.setVisibility(View.GONE);
v.icon.setVisibility(View.VISIBLE);
v.icon.setImageBitmap(result);
}
}
}.execute(holder);
从 Android 3.0 (API level 11)开始,对于AsyncTask有个新特性:在多核处理器的情况下,我们可以使用executeOnExecutor() 来替代execute(),这样系统会根据当前设备的内核数量同时执行多个任务。
Hold View Objects in a View Holder
你在滑动ListView时可能需要频繁地调用findViewById(),这样会降低性能。尽管Adapter会因为循环机制返回一个创建好的View。你仍然需要查找到这些组件并更新它,避免这样的重复,可使用“ViewHolder”设计模式。
一个ViewHolder对象缓存Layout里的每一个组件视图。因此你能立即的访问这些视图而不需要重复查询他们。首页,你需要产生一个ViewHolder类,如下:
static class ViewHolder {
TextView text;
TextView timestamp;
ImageView icon;
ProgressBar progress;
int position;
}
这样之后,我们可以填充这个ViewHolder,并且保存到tag属性里。
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);
那么我们就可以直接访问里面的数据了,省去了重复查询,提升了性能。