?
? ? ? ?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);
?
? ? ? ? ? 那么我们就可以直接访问里面的数据了,省去了重复查询,提升了性能。