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);

          那么我们就可以直接访问里面的数据了,省去了重复查询,提升了性能。

相关推荐