2015年2月5日木曜日

AndroidのListViewでNetworkから取得した画像をResize後にCacheする

こんにちは。岡田です。

今回は、AndroidのListViewでNetworkから取得した画像をResize後にCacheする方法について書いていく。
AndroidのListViewでImage ResourceをNetworkから取得する場合に
ViewがRefreshされる度に、画像を読み込みを行うとUsabilityが下がる。
このため一度取得したDataは内部でCacheし、再度取得に行かないように実装する。
また、取得した画像の横幅が、端末の横幅よりも広い場合は、画像をResizeする。

Android Studioで開発を行い、SourceはGitHubで公開している。

簡単に流れを下記に示す。

1. SimpleAdapterを継承したClass(ListTemplateAdapter)内のgetView()で、AsyncTaskを継承したClass(ImageGetTask)を呼び出し画像を取得する

imageView.setTag(thumbUrl);

ImageGetTask task = new ImageGetTask(imageView, waitBar);

task.execute(thumbUrl);

2. ImageGetTaskのdoInBackground内でCacheを確認し、空であればNetworkから画像を取得し、取得ができたらCacheに保存する

@Override

protected Bitmap doInBackground(String... params) {

    synchronized (context){

        try {

            Bitmap image = ImageCache.getImage(params[0]);

            if (image == null) {

                URL imageUrl = new URL(params[0]);

                image = getImage(imageUrl);

                ImageCache.setImage(params[0], image);

            }

            return image;

        } catch (MalformedURLException e) {

            return null;

        }

    }

}
 
3. 画像を取得し、画面の横幅よりも大きい画像の場合は、Resizeを行う

private Bitmap getImage(URL imageUrl) {

     InputStream inputStream = null;

     if (imageUrl != null) {

         try {

             inputStream = (InputStream) imageUrl.getContent();

         } catch (IOException e) {

             e.printStackTrace();

             return null;

         }

     }

     Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

     try {

         inputStream.close();

     } catch (IOException e) {

         e.printStackTrace();

         return null;

     }

     DisplayMetrics metrics = MetrixCache.get();

     if (metrics != null) {

         float scale = (float) bitmap.getWidth() / metrics.widthPixels;

         if (scale > 1) {

             int imageWidth = (int) (bitmap.getWidth() / scale);

             int imageHeight = (int) (bitmap.getHeight() / scale);

             bitmap = Bitmap.createScaledBitmap(

                     bitmap,

                     imageWidth,

                     imageHeight,

                     false);

         }

     }

     return bitmap;

 }

4. 取得した画像はクラス変数としてCacheする

public class ImageCache {

    private static HashMap<String,Bitmap> cache = new HashMap<String,Bitmap>();

    public static Bitmap getImage(String key) {

        if (cache.containsKey(key)) {

            return cache.get(key);

        }

        return null;

    }

    public static void setImage(String key, Bitmap image) {

        cache.put(key, image);

    }

    public static void clearCache(){

        cache = null;

        cache = new HashMap<String,Bitmap>();

    }

}
5. ImageGetTaskのonPostExecute内で画像を設定する

@Override

protected void onPostExecute(Bitmap result) {

    if(tag.equals(image.getTag())){

        if(result!=null){

            image.setImageBitmap(result);

        }

        else{

image.setImageDrawable(context.getResources().getDrawable(android.R.drawable.ic_notification_clear_all));

        }

        progress.setVisibility(View.GONE);

        image.setVisibility(View.VISIBLE);

    }

}

0 件のコメント :

コメントを投稿