2012-02-23 154 views
1

我正在制作一个Android应用程序,我试图在列表视图中加载和缓存图像。我从here得到了代码。这个Github项目的例子对我来说工作得很好,但是当我尝试在我的应用程序中使用相同的例子时,它的dosnt工作。这是我的ImageManager类。图像不延迟加载和缓存

public class ImageManager { 

    private HashMap<String, SoftReference<Bitmap>> imageMap = new HashMap<String, SoftReference<Bitmap>>(); 

    private File cacheDir; 
    private ImageQueue imageQueue = new ImageQueue(); 
    private Thread imageLoaderThread = new Thread(new ImageQueueManager()); 

    public ImageManager(Context context) { 
     // Make background thread low priority, to avoid affecting UI 
     // performance 
     imageLoaderThread.setPriority(Thread.NORM_PRIORITY - 1); 

     // Find the dir to save cached images 
     String sdState = android.os.Environment.getExternalStorageState(); 
     if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) { 
      File sdDir = android.os.Environment.getExternalStorageDirectory(); 
      cacheDir = new File(sdDir, "data/floapp"); 
      System.out 
        .println("coming here in mounted media and created folder floapp"); 
     } else 
      cacheDir = context.getCacheDir(); 

     if (!cacheDir.exists()) 
      cacheDir.mkdirs(); 
    } 

    public void displayImage(String url, Activity activity, ImageView imageView) { 
     if (imageMap.containsKey(url)) { 

      imageView.setImageBitmap(imageMap.get(url).get()); 
     } else { 
      queueImage(url, activity, imageView); 
      imageView.setImageResource(R.drawable.ic_launcher); 
     } 
    } 

    private void queueImage(String url, Activity activity, ImageView imageView) { 
     // This ImageView might have been used for other images, so we clear 
     // the queue of old tasks before starting. 
     imageQueue.Clean(imageView); 
     ImageRef p = new ImageRef(url, imageView); 
     synchronized (imageQueue.imageRefs) { 
      imageQueue.imageRefs.push(p); 
      imageQueue.imageRefs.notifyAll(); 
     } 

     // Start thread if it's not started yet 
     if (imageLoaderThread.getState() == Thread.State.NEW) 
      imageLoaderThread.start(); 
    } 

    private Bitmap getBitmap(String url) { 
     System.out.println("coming in getbitmap"); 
     String filename = String.valueOf(url.hashCode()); 
     File f = new File(cacheDir, filename); 
     System.out.println("cachedir=" + cacheDir.getPath()); 
     System.out.println("filename=" + filename); 

     // Is the bitmap in our cache? 
     Bitmap bitmap = BitmapFactory.decodeFile(f.getPath()); 
     System.out.println("bitmap after decoding the file thingy file path=" 
       + f.getPath()); 
     if (bitmap != null) 
      return bitmap; 

     // Nope, have to download it 
     try { 
      bitmap = BitmapFactory.decodeStream(new URL(url).openConnection() 
        .getInputStream()); 
      // save bitmap to cache for later 
      writeFile(bitmap, f); 
      return bitmap; 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } 

    private void writeFile(Bitmap bmp, File f) { 
     FileOutputStream out = null; 

     try { 
      out = new FileOutputStream(f); 
      bmp.compress(Bitmap.CompressFormat.PNG, 80, out); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       if (out != null) 
        out.close(); 
      } catch (Exception ex) { 
      } 
     } 
    } 

    /** Classes **/ 

    private class ImageRef { 
     public String url; 
     public ImageView imageView; 

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

    // stores list of images to download 
    private class ImageQueue { 
     private Stack<ImageRef> imageRefs = new Stack<ImageRef>(); 

     // removes all instances of this ImageView 
     public void Clean(ImageView view) { 

      for (int i = 0; i < imageRefs.size();) { 
       if (imageRefs.get(i).imageView == view) 
        imageRefs.remove(i); 
       else 
        ++i; 
      } 
     } 
    } 

    private class ImageQueueManager implements Runnable { 
     // @Override 
     public void run() { 
      try { 
       while (true) { 
        // Thread waits until there are images in the 
        // queue to be retrieved 
        if (imageQueue.imageRefs.size() == 0) { 
         synchronized (imageQueue.imageRefs) { 
          imageQueue.imageRefs.wait(); 
         } 
        } 

        // When we have images to be loaded 
        if (imageQueue.imageRefs.size() != 0) { 
         ImageRef imageToLoad; 

         synchronized (imageQueue.imageRefs) { 
          imageToLoad = imageQueue.imageRefs.pop(); 
         } 

         Bitmap bmp = getBitmap(imageToLoad.url); 
         imageMap.put(imageToLoad.url, 
           new SoftReference<Bitmap>(bmp)); 
         Object tag = imageToLoad.imageView.getTag(); 

         // Make sure we have the right view - thread safety 
         // defender 
         if (tag != null 
           && ((String) tag).equals(imageToLoad.url)) { 
          BitmapDisplayer bmpDisplayer = new BitmapDisplayer(
            bmp, imageToLoad.imageView); 

          Activity a = (Activity) imageToLoad.imageView 
            .getContext(); 

          a.runOnUiThread(bmpDisplayer); 
         } 
        } 

        if (Thread.interrupted()) 
         break; 
       } 
      } catch (InterruptedException e) { 
      } 
     } 
    } 

    // Used to display bitmap in the UI thread 
    private class BitmapDisplayer implements Runnable { 
     Bitmap bitmap; 
     ImageView imageView; 

     public BitmapDisplayer(Bitmap b, ImageView i) { 
      bitmap = b; 
      imageView = i; 
     } 

     public void run() { 
      if (bitmap != null) 
       imageView.setImageBitmap(bitmap); 
      else { 
       imageView.setImageResource(R.drawable.ic_launcher); 
      } 
     } 
    } 
} 

我得到FileNotFoundException,但文件正在我的SD卡上的文件夹中创建。谁能帮帮我吗??
- 预先感谢

更新: 我想这跟url有关。我从here得到了一个提示。我的网址是这样的 “http://graph.facebook.com/1519317701/picture

+0

where throw'FileNotFoundException','cacheDir = new File(sdDir,“data/floapp”);'here或where? – idiottiger 2012-02-23 09:56:50

+0

对不起,我的坏。早些时候应该提到它。错误在位图bitmap = BitmapFactory.decodeFile(f.getPath()); – Antrromet 2012-02-23 09:59:09

+0

打印语句工作得很好。 cachedir的输出是 cachedir =/mnt/sdcard/data/floapp – Antrromet 2012-02-23 10:01:33

回答

2
+0

我得到相同的错误。我正在使用第一个链接'lazy list with fedor'以及ImageLoader类中的decodeFile(),我正在将文件f.getpath()打印为“/ mnt/sdcard/LazyList/1534745000”并正确打印在BitmapFactory.decodeStream中(新的FileInputStream(f),null,o);我得到一个异常为“java.io.FileNotFoundException:/ mnt/sdcard/LazyList/1534745000(没有这样的文件或目录)”。 – Antrromet 2012-02-23 10:50:59

+0

我想它的问题是相同的,代码很好,只是它不能从中解码流。我不知道为什么:(我已经浪费了很多时间在这...请帮助。 – Antrromet 2012-02-23 10:52:35

+0

请看看我更新的问题,并抛出一些光,如果可以! – Antrromet 2012-02-23 11:05:56

0

我瞎猜这里.. 。我遇到了同样的问题,并且通过将“android.permission.WRITE_EXTERNAL_STORAGE”权限添加到我的应用程序清单中来修复它。虽然您可能已经添加了它...

+0

是的......我已经添加了该权限。 – Antrromet 2012-02-29 04:19:21

2

另一个好的解决方案是ImageLoader(http://androidimageloader.com)。这提供了异步图像加载和透明的双级缓存。