平滑滚动ListView
的关键是保持应用程序的主线程(UI线程)免于繁重的处理。
确保在单独的线程中执行任何磁盘访问,网络访问或SQL
访问。 要测试应用程序的状态,您可以启用StrictMode
。
一、使用后台线程
使用后台线程(“工作线程”)消除主线程的压力,使其可以专注于绘制UI。 在许多情况下,使用AsyncTask
提供了一种在主线程外执行工作的简单方法。 AsyncTask
自动将所有execute()
请求排队并按顺序执行。 此行为对于特定进程是全局的,这意味着您无需担心创建自己的线程池。
在下面的示例代码中,AsyncTask
用于在后台线程中加载图像,然后在完成后将它们应用到UI
。 它还会在加载时显示进度微调器代替图像。
// 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级别11)开始,AsyncTask
中提供了一项额外功能,因此您可以使其在多个处理器核心上运行。 您可以指定executeOnExecutor()
而不是调用execute()
,并且可以根据可用的内核数量同时执行多个请求。
二、在视图持有者中保持视图对象
在滚动ListView
期间,您的代码可能经常调用findViewById()
,这会降低性能。 即使适配器返回一个膨胀的视图以进行回收,您仍然需要查找元素并更新它们。 绕过重复使用findViewById()
的方法是使用“view holder”
设计模式。
ViewHolder
对象将每个组件视图存储在Layout
的标记字段中,因此您可以立即访问它们而无需重复查找它们。 首先,您需要创建一个类来保存您的确切视图集。 例如:
static class ViewHolder {
TextView text;
TextView timestamp;
ImageView icon;
ProgressBar progress;
int position;
}
然后填充ViewHolder
并将其存储在布局中。
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);
现在,您无需查询即可轻松访问每个视图,从而节省宝贵的处理器周期。
网友评论