【问题标题】:Images not Lazy Loading and Caching图像不延迟加载和缓存
【发布时间】:2012-03-13 17:10:06
【问题描述】:

我正在制作一个 android 应用程序,我试图在其中延迟加载和缓存列表视图中的图像。我从here 得到代码。这个Github 项目中的示例对我来说非常好,但是当我尝试在我的应用程序中使用相同的示例时,它不起作用。这是我的 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,但文件是在我的 sdcard 上的文件夹中创建的。谁能帮帮我??
-提前致谢

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

【问题讨论】:

  • 在哪里扔FileNotFoundException, cacheDir = new File(sdDir, "data/floapp");这里还是哪里?
  • 对不起,我的错。早该提到的。错误在 Bitmap bitmap = BitmapFactory.decodeFile(f.getPath());
  • 打印语句运行良好。 cachedir的输出是cachedir=/mnt/sdcard/data/floapp
  • 如果在decodeFile,可以输出路径查看一下,可能路径不存在。
  • 我正在打印文件路径,它按预期正确打印。它在解码文件thingy file path=/mnt/sdcard/data/floapp/-2088703618后打印'位图'

标签: android image file listview caching


【解决方案1】:

【讨论】:

  • 我遇到了同样的错误。我正在使用第一个链接'Lazy list with images by fedor',在 ImageLoader 类 decodeFile() 中,我正在打印文件 f.getpath() 并将其正确打印为“/mnt/sdcard/LazyList/1534745000”和在 BitmapFactory.decodeStream(new FileInputStream(f), null, o);我得到一个异常为“java.io.FileNotFoundException:/mnt/sdcard/LazyList/1534745000(没有这样的文件或目录)”。
  • 我猜它是同样的问题,代码很好,只是它无法从中解码流。我不知道为什么:(我已经在这上面浪费了很多时间......请帮忙。
  • 请查看我更新的问题,如果可以的话,请提供一些启示!
  • 我的问题仍未解决,但我尝试了上面的第一个链接,它对我有用。
  • 通用图像加载器是我认为最好的解决方案,因为它适用于 ListView、Gallery、GridView .....
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    我在这里猜测一下......我遇到了同样的问题,我通过在我的应用程序清单中添加“android.permission.WRITE_EXTERNAL_STORAGE”权限来解决它。虽然您可能已经添加了它...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-24
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多