2011-05-03 3 views
1

나는 웹에서 이미지를 다운로드하는이 클래스가 있으며 다운로드 한 이미지가 SDCard에 저장되도록 아래 코드를 수정하도록 도와 줄 누군가가 필요합니다. 인터넷에서이 코드를 가져오고 초보자이기 때문에 캐시 작업을 위해이 코드를 최적화하는 것이 꽤 우둔합니다.Android : 이미지를 다운로드하여 캐시로 저장하십시오.

나는 모든 종류의 솔루션에 개방적입니다. 감사합니다.

public class ImageThreadLoader { 
    private static final String TAG = "ImageThreadLoader"; 

    // Global cache of images. 
    // Using SoftReference to allow garbage collector to clean cache if needed 
    private final HashMap<String, SoftReference<Bitmap>> Cache = new HashMap<String, SoftReference<Bitmap>>(); 

    private final class QueueItem { 
     public URL url; 
     public ImageLoadedListener listener; 
    } 
    private final ArrayList<QueueItem> Queue = new ArrayList<QueueItem>(); 

    private final Handler handler = new Handler(); // Assumes that this is started from the main (UI) thread 
    private Thread thread; 
    private QueueRunner runner = new QueueRunner();; 

    /** Creates a new instance of the ImageThreadLoader */ 
    public ImageThreadLoader() { 
     thread = new Thread(runner); 
    } 

    /** 
    * Defines an interface for a callback that will handle 
    * responses from the thread loader when an image is done 
    * being loaded. 
    */ 
    public interface ImageLoadedListener { 
     public void imageLoaded(Bitmap imageBitmap); 
    } 

    /** 
    * Provides a Runnable class to handle loading 
    * the image from the URL and settings the 
    * ImageView on the UI thread. 
    */ 
    private class QueueRunner implements Runnable { 
     public void run() { 
      synchronized(this) { 
       while(Queue.size() > 0) { 
        final QueueItem item = Queue.remove(0); 

        // If in the cache, return that copy and be done 
        if(Cache.containsKey(item.url.toString()) && Cache.get(item.url.toString()) != null) { 
         // Use a handler to get back onto the UI thread for the update 
         handler.post(new Runnable() { 
          public void run() { 
           if(item.listener != null) { 
            // NB: There's a potential race condition here where the cache item could get 
            //  garbage collected between when we post the runnable and it's executed. 
            //  Ideally we would re-run the network load or something. 
            SoftReference<Bitmap> ref = Cache.get(item.url.toString()); 
            if(ref != null) { 
             item.listener.imageLoaded(ref.get()); 
            } 
           } 
          } 
         }); 
        } else { 
         final Bitmap bmp = readBitmapFromNetwork(item.url); 
         if(bmp != null) { 
          Cache.put(item.url.toString(), new SoftReference<Bitmap>(bmp)); 

          // Use a handler to get back onto the UI thread for the update 
          handler.post(new Runnable() { 
           public void run() { 
            if(item.listener != null) { 
             item.listener.imageLoaded(bmp); 
            } 
           } 
          }); 
         } 

        } 

       } 
      } 
     } 
    } 

    /** 
    * Queues up a URI to load an image from for a given image view. 
    * 
    * @param uri The URI source of the image 
    * @param callback The listener class to call when the image is loaded 
    * @throws MalformedURLException If the provided uri cannot be parsed 
    * @return A Bitmap image if the image is in the cache, else null. 
    */ 
    public Bitmap loadImage(final String uri, final ImageLoadedListener listener) throws MalformedURLException { 
     // If it's in the cache, just get it and quit it 
     if(Cache.containsKey(uri)) { 
      SoftReference<Bitmap> ref = Cache.get(uri); 
      if(ref != null) { 
       return ref.get(); 
      } 
     } 

     QueueItem item = new QueueItem(); 
     item.url = new URL(uri); 
     item.listener = listener; 
     Queue.add(item); 

     // start the thread if needed 
     if(thread.getState() == State.NEW) { 
      thread.start(); 
     } else if(thread.getState() == State.TERMINATED) { 
      thread = new Thread(runner); 
      thread.start(); 
     } 
     return null; 
    } 

    /** 
    * Convenience method to retrieve a bitmap image from 
    * a URL over the network. The built-in methods do 
    * not seem to work, as they return a FileNotFound 
    * exception. 
    * 
    * Note that this does not perform any threading -- 
    * it blocks the call while retrieving the data. 
    * 
    * @param url The URL to read the bitmap from. 
    * @return A Bitmap image or null if an error occurs. 
    */ 
    public static Bitmap readBitmapFromNetwork(URL url) { 
     InputStream is = null; 
     BufferedInputStream bis = null; 
     Bitmap bmp = null; 
     try { 
      URLConnection conn = url.openConnection(); 
      conn.connect(); 
      is = conn.getInputStream(); 
      bis = new BufferedInputStream(is); 
      bmp = BitmapFactory.decodeStream(bis); 
     } catch (MalformedURLException e) { 
      Log.e(TAG, "Bad ad URL", e); 
     } catch (IOException e) { 
      Log.e(TAG, "Could not get remote ad image", e); 
     } finally { 
      try { 
       if(is != null) 
        is.close(); 
       if(bis != null) 
        bis.close(); 
      } catch (IOException e) { 
       Log.w(TAG, "Error closing stream."); 
      } 
     } 
     return bmp; 
    } 

} 

답변

5

당신은 비트 맵 클래스의 압축 방법을 사용하여 비트 맵을 저장할 수 있습니다 : here

내 자신의 코드는 다음과 같습니다 그것은 당신이 SD 카드에 비트 맵을 작성할 수 있습니다

FileOutputStream os = null; 
try { 
    os = new FileOutputStream(
      new File( 
        android.os.Environment.getExternalStorageDirectory().getAbsolutePath(), 
       fileName)); 

    bitmap.compress(Bitmap.CompressFormat.JPEG, 90, os); 
} catch (FileNotFoundException e) { 
    e.printStackTrace(); 
} 
finally { 
    if (os != null) { 
     try { 
      os.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

. android.os.environment.getExternalStorageDirectory().canRead()android.os.environment.getExternalStorageDirectory().canWrite() 방법 : 읽고 사용하여 SD 카드에 쓸 수있는 경우도 확인해야합니다 here

:

BitmapFactory 클래스에서 decodeFile() 방법을 사용하여 SD 카드에 저장된 비트 맵을 엽니 다.

+0

당신의 코드를 구현하는 방법은 비슷한 질문이 있습니다. –

관련 문제