2014年10月7日火曜日

android Volleyを使ったListViewをリファクタリング

さてさて。久しぶりに会社絡み抜きでandroidアプリを作成しているのですが、もうひと踏ん張りで終了しそうです。

というわけで、今回はリファクタリングに焦点を当てます

環境

  • android:minSdkVersion="14"
  • android:targetSdkVersion="19"

volleyを利用したListViewの画像取得をキャッシュする

volleyはここ半年くらいで利用し始めました。とっても便利なライブラリです。デフォルトでも十分な性能ですが、チューニングするとさらにすばらしいことに!

リファクタリング前
よくありがちなVolleyを使ったListView処理です。


        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {

            View row = convertView;
            if (row == null) {
                LayoutInflater inflater = getActivity().getLayoutInflater();
                row = inflater.inflate(R.layout.fragment_user_row, parent, false);
            }

            UserPojo userPojo = mViewList.get(position);

            ImageView userImage = (ImageView) row.findViewById(R.id.user_image);
            ImageLoader.ImageListener userImageListener = ImageLoader.getImageListener(userImage, R.drawable.image_loading, R.drawable.no_image);
            userImage.setTag(mImageLoader.get(userPojo.user_image_path, userImageListener));

            TextView userName = (TextView) row.findViewById(R.id.user_name);
            userName.setText(userPojo.user_name);

            TextView startTime = (TextView) row.findViewById(R.id.start_time);
            startTime.setText(userPojo.clime_start_time);

            userPojo = null;

            return row;
        }

上記をViewHolderパターンとCancelRequestパターンを実装して書き換えます。

リファクタリング後


        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {

            ViewHolder holder;
            if (convertView == null) {
                LayoutInflater inflater = getActivity().getLayoutInflater();
                convertView = inflater.inflate(R.layout.fragment_user_row, parent, false);
                holder = new ViewHolder(convertView);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            View row = convertView;
            if (row == null) {
                LayoutInflater inflater = getActivity().getLayoutInflater();
                row = inflater.inflate(R.layout.fragment_user_row, parent, false);
            }

            // リクエストのキャンセル処理
            ImageLoader.ImageContainer imageContainer = (ImageLoader.ImageContainer)holder.userImage.getTag();
            if (imageContainer != null) {
                imageContainer.cancelRequest();
            }

            UserPojo userPojo = mViewList.get(position);

            ImageView userImage = (ImageView) row.findViewById(R.id.user_image);
            ImageLoader.ImageListener userImageListener = ImageLoader.getImageListener(userImage, R.drawable.image_loading, R.drawable.no_image);
            userImage.setTag(mImageLoader.get(userPojo.user_image_path, userImageListener));

            holder.userName.setText(userPojo.user_name);
            holder.startTime.setText(userPojo.start_time);

            return convertView;
        }

        /**
         * View holder pattern
         */
        private class ViewHolder {
            ImageView userImage;
            TextView userName;
            TextView startTime;

            public ViewHolder(View view) {
                this.userImage = (ImageView) view.findViewById(R.id.user_image);
                this.userName = (TextView) view.findViewById(R.id.user_name);
                this.startTime = (TextView) view.findViewById(R.id.start_time);
            }
        }

リストの一行のviewをViewHolderクラスを作ってキャッシュし、Viewの再利用時にImageViewからImageContainerのインスタンスを取得し、リクエストのキャンセルを行っています。

リファクタリング前と比較すると相当軽く、速くなります。

p.s 2014年8月までならこれでリファクタリング終了ですが、android Lが使えるようになると、RecyclerViewを使ってさらに高速化できるようです。これは正式版がリリースされたら説明したいと思います。

参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

0 件のコメント:

コメントを投稿

Related Posts Plugin for WordPress, Blogger...