반응형
Notice
Recent Posts
Recent Comments
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

Do Something IT

[안드로이드] lazyImageLoader 본문

Android

[안드로이드] lazyImageLoader

아낙시만더 2010. 12. 20. 13:57
반응형

많은 양의 Image를 다운 받아 표시할때 미리 이미지를 하나 깔고 천천히 이미지를 깔아 줌으로써 속도를 진척 시키는 커스텀 클래스이다.


package my.android.com;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

public class ImageLoader {

 private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();
 private PhotosQueue photosQueue = new PhotosQueue();
 private PhotosLoader photoLoaderThread = new PhotosLoader();
 private MusicListAdapter TopAdapter;
 private final int stub_id = R.drawable.noimage;
 private File cacheDir;

 public ImageLoader(Context context) {
  // Make the background thead low priority. This way it will not affect
  // the UI performance
  photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
  // Find the dir to save cached images
  if (android.os.Environment.getExternalStorageState().equals(
    android.os.Environment.MEDIA_MOUNTED))
   cacheDir = new File(
     android.os.Environment.getExternalStorageDirectory(),
     "LazyList");
  else
   cacheDir = context.getCacheDir();
  if (!cacheDir.exists())
   cacheDir.mkdirs();
 }

 // Task for the queue
 private class PhotoToLoad {
  public String url;
  public ImageView imageView;

  public PhotoToLoad(String u, ImageView i) {
   url = u;
   imageView = i;
  }
 }

 // Used to display bitmap in the UI thread
 // class BitmapDisplayer implements Runnable {
 // Bitmap bitmap;
 // ImageView imageView;
 //
 // public BitmapDisplayer(Bitmap b, ImageView i) {
 // bitmap = b;
 // imageView = i;
 // }
 //
 // public void run() {
 //
 // if (bitmap != null) {
 // System.out.println("bitmap is not null");
 // imageView.setImageBitmap(bitmap);
 // } else {
 // System.out.println("bitmap is null");
 // imageView.setImageResource(stub_id);
 // }
 // }
 // }

 // stores list of photos to download
 class PhotosQueue {
  private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();

  // removes all instances of this ImageView
  public void Clean(ImageView image) {
   for (int j = 0; j < photosToLoad.size();) {
    if (photosToLoad.get(j).imageView == image)
     photosToLoad.remove(j);
    else
     ++j;
   }
  }
 }

 class PhotosLoader extends Thread {
  public void run() {
   try {
    /* 무한 반복한다. */
    while (true) {
     // thread waits until there are any images to load in the
     // queue
     if (photosQueue.photosToLoad.size() == 0)
      synchronized (photosQueue.photosToLoad) {
       photosQueue.photosToLoad.wait();
      }
     if (photosQueue.photosToLoad.size() != 0) {
      PhotoToLoad photoToLoad;
      synchronized (photosQueue.photosToLoad) {
       photoToLoad = photosQueue.photosToLoad.pop();
      }
      Bitmap bmp = getBitmap(photoToLoad.url);
      cache.put(photoToLoad.url, bmp);
      // Object tag = photoToLoad.imageView.getTag();
      // if (tag != null
      // && ((String) tag).equals(photoToLoad.url)) {
      // BitmapDisplayer bd = new BitmapDisplayer(bmp,
      // photoToLoad.imageView);
      // Thread thread = new Thread(bd);
      // thread.start();
      // Activity a = (Activity) photoToLoad.imageView
      // .getContext();
      // a.runOnUiThread(bd);
      // }
      /* 이미지를 set한후 notify를 호출한다. */
      mAfterImageSet.sendEmptyMessage(0);
     }
     if (Thread.interrupted())
      break;
    }
   } catch (InterruptedException e) {
    // allow thread to exit
   }
  }
 }

 Handler mAfterImageSet = new Handler() {
  public void handleMessage(Message msg) {
   TopAdapter.notifyDataSetChanged();
  }
 };

 /* 초반 이미지를 셋시키는 메소드 cache해쉬에 값이 있으면 해당 이미지를 셋 하고 없으면 이미지 없음을 표시한다. */
 public void DisplayImage(String url, Activity activity,
   ImageView imageView, MusicListAdapter pAdapter) {
  TopAdapter = pAdapter;
  if (cache.containsKey(url))
   if (!(cache.get(url) == null))
    imageView.setImageBitmap(cache.get(url));
   else
    imageView.setImageResource(stub_id);
  else {
   queuePhoto(url, activity, imageView);
   imageView.setImageResource(stub_id);
  }
 }

 /*
  * photosQueue의 stack을 초기화시키고 아답터에서 받아온 이미지를 데이터 타입클래스에 셋 시킨후 스텍에 삽입한후 다른
  * 스레드에게 알려준다. 만약 스레드가 시작 되지 않았다면 스레드를 스타트 합니다.
  */
 private void queuePhoto(String url, Activity activity, ImageView imageView) {
  // This ImageView may be used for other images before. So there may be
  // some old tasks in the queue. We need to discard them.
  photosQueue.Clean(imageView);
  PhotoToLoad p = new PhotoToLoad(url, imageView);
  synchronized (photosQueue.photosToLoad) {// 임계 영역 설정 임계영역으로 스택이 들어온다.
   photosQueue.photosToLoad.push(p);// 이녀석은 아답터를 통해 드러온 이미지를 저장한다.
   photosQueue.photosToLoad.notifyAll(); // 스택에 새 값이 들어 왔다고 다른 스레들에게
             // 알린다.
  }

  // start thread if it's not started yet 스레드가 시작이 되지 않았을때는 스레드를 시작시킨다.
  if (photoLoaderThread.getState() == Thread.State.NEW)
   photoLoaderThread.start();
 }

 public Bitmap getBitmap(String url) {
  // I identify images by hashcode. Not a perfect solution, good for the
  // demo.
  String filename = String.valueOf(url.hashCode());
  File f = new File(cacheDir, filename);
  // from SD cache
  Bitmap b = decodeFile(f);
  if (b != null)
   return b;
  // from web
  try {
   Bitmap bitmap = null;
   InputStream is = new URL(url).openStream();
   OutputStream os = new FileOutputStream(f);
   Utils.CopyStream(is, os);
   os.close();
   bitmap = decodeFile(f);
   return bitmap;
  } catch (Exception ex) {
   ex.printStackTrace();
   return null;
  }
 }

 // decodes image and scales it to reduce memory consumption
 private Bitmap decodeFile(File f) {
  try {
   // decode image size
   BitmapFactory.Options o = new BitmapFactory.Options();
   o.inJustDecodeBounds = true;
   BitmapFactory.decodeStream(new FileInputStream(f), null, o);

   // Find the correct scale value. It should be the power of 2.
   final int REQUIRED_SIZE = 70;
   int width_tmp = o.outWidth, height_tmp = o.outHeight;
   int scale = 1;
   while (true) {
    if (width_tmp / 2 < REQUIRED_SIZE
      || height_tmp / 2 < REQUIRED_SIZE)
     break;
    width_tmp /= 2;
    height_tmp /= 2;
    scale *= 2;
   }

   // decode with inSampleSize
   BitmapFactory.Options o2 = new BitmapFactory.Options();
   o2.inSampleSize = scale;
   return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
  } catch (FileNotFoundException e) {
  }
  return null;
 }

 // private Bitmap getBitmap(String url)
 // {
 // Bitmap albumImage = null;
 // URL myFileUrl = null;
 // if(url.toString()!=""){
 // try {
 // if(!url.toString().substring(0, 4).equals("http")){
 // String urlTemp=url.toString().substring(8, url.toString().length());
 // System.out.println(" change  string "+urlTemp);
 // myFileUrl = new URL(urlTemp);
 // }else{
 // myFileUrl = new URL(url.toString());
 // }
 // HttpURLConnection conn = (HttpURLConnection) myFileUrl
 // .openConnection();
 // conn.setDoInput(true);
 // conn.connect();
 // InputStream is = conn.getInputStream();
 // albumImage = BitmapFactory.decodeStream(is);
 // } catch (IOException e) {
 // e.printStackTrace();
 // }
 // return albumImage;
 // }else
 // return null;
 // }

 public void stopThread() {
  photoLoaderThread.interrupt();
 }

 public void clearCache() {
  // clear memory cache
  cache.clear();
  // clear SD cache
  File[] files = cacheDir.listFiles();
  for (File f : files)
   f.delete();
 }

}


=======[Utills.java]=======
public class Utils {
    public static void CopyStream(InputStream is, OutputStream os)
    {
        final int buffer_size=1024;
        try
        {
            byte[] bytes=new byte[buffer_size];
            for(;;)
            {
              int count=is.read(bytes, 0, buffer_size);
              if(count==-1)
                  break;
              os.write(bytes, 0, count);
            }
        }
        catch(Exception ex){}
    }
 /**
  * Random 수를 리턴 한다.
  *
  * @param start
  * @param end
  * @return Random 수
  */
 public static int getRandom( int start , int end )
 {
  Random random = new Random();
  return (Math.abs(random.nextInt()) % (end - start + 1)) + start;
 }   
}

반응형
Comments