Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android图像缓存_Android_Image_Caching - Fatal编程技术网

Android图像缓存

Android图像缓存,android,image,caching,Android,Image,Caching,从web下载图像后,如何缓存图像?将其转换为位图,然后将其存储在集合(哈希图、列表等)中,或者您可以将其写入SD卡 当使用第一种方法将它们存储在应用程序空间中时,您可能希望将它们包装在java.lang.ref.SoftReference中,特别是当它们的数量很大时(以便在危机期间将它们垃圾收集)。不过,这可能会导致重新加载 HashMap<String,SoftReference<Bitmap>> imageCache = new HashMap<

从web下载图像后,如何缓存图像?

将其转换为位图,然后将其存储在集合(哈希图、列表等)中,或者您可以将其写入SD卡

当使用第一种方法将它们存储在应用程序空间中时,您可能希望将它们包装在java.lang.ref.SoftReference中,特别是当它们的数量很大时(以便在危机期间将它们垃圾收集)。不过,这可能会导致重新加载

HashMap<String,SoftReference<Bitmap>> imageCache =
        new HashMap<String,SoftReference<Bitmap>>();
HashMap图像缓存=
新的HashMap();

将它们写入SD卡不需要重新加载;只有用户权限。

要下载图像并保存到存储卡,您可以这样做

//First create a new URL object 
URL url = new URL("http://www.google.co.uk/logos/holiday09_2.gif")

//Next create a file, the example below will save to the SDCARD using JPEG format
File file = new File("/sdcard/example.jpg");

//Next create a Bitmap object and download the image to bitmap
Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());

//Finally compress the bitmap, saving to the file previously created
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));
不要忘记将Internet权限添加到您的清单中:

<uses-permission android:name="android.permission.INTERNET" />


<代码> > p>我会考虑使用DoRIDFU的图像缓存。它实现了内存和基于磁盘的映像缓存。您还可以获得利用ImageCache库的WebImageView

以下是droidfu和WebImageView的完整描述:

现在是关键:使用系统缓存

URL url = new URL(strUrl);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (response instanceof Bitmap) {
  Bitmap bitmap = (Bitmap)response;
} 
提供与浏览器共享的内存和闪存rom缓存


grr。在我编写自己的缓存管理器之前,我希望有人告诉我这一点。

关于优雅的
连接。上面的setUseCaches
解决方案:遗憾的是,如果没有额外的努力,它将无法工作。您需要使用
ResponseCache.setDefault
安装
ResponseCache
。否则,
HttpURLConnection
将自动忽略
setUseCaches(true)

有关详细信息,请参见
FileResponseCache.java
顶部的注释:


(我会在评论中发表这篇文章,但我显然没有足够的因果关系。)

我尝试过软引用,它们在android中被积极回收,我觉得使用它们没有任何意义。上面的代码示例有两个问题-一个-响应对象不是位图的实例(当我的URL引用jpg时,如http:\website.com\image.jpg,它是一个

org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl$LimitedInputStream)

其次,正如Joe指出的,如果没有配置响应缓存,就不会发生缓存。Android开发人员只能自己滚动缓存。这里有一个这样做的例子,但它只缓存在内存中,这并不是完整的解决方案

URLConnection缓存API如下所述:


我仍然认为这是一个可以走这条路的解决方案,但是你仍然需要写一个缓存。听起来很有趣,但我更喜欢写特写

回答晚了,但我想我应该添加一个链接到我的站点,因为我已经写了一篇教程,介绍了如何为android创建图像缓存:更新:由于源代码过时,该页面已脱机。我加入了@elenasys的使用建议


所以,对于所有偶然发现这个问题却没有找到解决办法的人:希望你们喜欢=D

我一直在努力解决这个问题,已经有一段时间了;使用软引用的答案会很快丢失数据。建议实例化RequestCache的答案太混乱了,而且我从来没有找到完整的示例


但对我来说效果非常好。它使用哈希映射,直到达到容量或清除超时,然后将内容移动到软引用,从而充分利用这两个方面。

谷歌android版libs有一个很好的库,用于管理图像和文件缓存


正如雷霆兔所建议的,ImageDownloader是这项工作的最佳选择。我还发现课程在以下方面略有不同:


两者之间的主要区别在于ImageDownloader使用Android缓存系统,而修改后的ImageDownloader使用内部和外部存储作为缓存,无限期地保留缓存的图像,或者直到用户手动删除。作者还提到了Android 2.1的兼容性。

在Android的官方培训部分有一个特别的条目:

这一部分是相当新的,当被问到这个问题时,它并不在那里

建议的解决方案是使用LruCache。该类是在蜂巢上引入的,但它也包含在兼容性库中

您可以通过设置最大数量或条目来初始化LruCache,当您超过限制时,它将自动对它们进行排序,并清除使用较少的条目。除此之外,它还用作法线贴图

来自官方页面的示例代码:

private LruCache mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get memory class of this device, exceeding this amount will throw an
    // OutOfMemory exception.
    final int memClass = ((ActivityManager) context.getSystemService(
            Context.ACTIVITY_SERVICE)).getMemoryClass();

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = 1024 * 1024 * memClass / 8;

    mMemoryCache = new LruCache(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number of items.
            return bitmap.getByteCount();
        }
    };
    ...
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
}
以前的软参考是一个很好的选择,但现在不是了,从官方页面引用:

private LruCache mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get memory class of this device, exceeding this amount will throw an
    // OutOfMemory exception.
    final int memClass = ((ActivityManager) context.getSystemService(
            Context.ACTIVITY_SERVICE)).getMemoryClass();

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = 1024 * 1024 * memClass / 8;

    mMemoryCache = new LruCache(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number of items.
            return bitmap.getByteCount();
        }
    };
    ...
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
}
注意:在过去,流行的内存缓存实现是 SoftReference或WeakReference位图缓存,但这不是 推荐。从Android 2.3(API级别9)开始,垃圾 收集器在收集软/弱引用时更具攻击性 这使得它们相当无效。此外,在Android 3.0之前 (API级别11),位图的备份数据存储在本机中 未以可预测的方式释放的内存,可能 导致应用程序短暂超出其内存限制并崩溃


我建议点火这甚至比Droid fu更好

考虑使用。它附带:

  • 多线程图像加载。它允许您定义线程池大小
  • 图像缓存在内存、设备文件系统和SD卡上
  • 监听加载进度和加载事件的可能性
Universal Image Loader允许使用以下缓存配置对下载的图像进行详细的缓存管理:

  • 使用FreqLimitedMemoryCache
    :超过缓存大小限制时,将删除最不常用的位图
  • LRULimitedMemoryCache
    :超过缓存大小限制时,删除最近使用最少的位图try { File httpCacheDir = new File(getApplicationContext().getCacheDir(), "http"); long httpCacheSize = 10 * 1024 * 1024; // 10 MiB HttpResponseCache.install(httpCacheDir, httpCacheSize); } catch (IOException e) { }
connection.setUseCaches(true);
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

public class ImagesCache 
{
    private  LruCache<String, Bitmap> imagesWarehouse;

    private static ImagesCache cache;

    public static ImagesCache getInstance()
    {
        if(cache == null)
        {
            cache = new ImagesCache();
        }

        return cache;
    }

    public void initializeCache()
    {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() /1024);

        final int cacheSize = maxMemory / 8;

        System.out.println("cache size = "+cacheSize);

        imagesWarehouse = new LruCache<String, Bitmap>(cacheSize)
                {
                    protected int sizeOf(String key, Bitmap value) 
                    {
                        // The cache size will be measured in kilobytes rather than number of items.

                        int bitmapByteCount = value.getRowBytes() * value.getHeight();

                        return bitmapByteCount / 1024;
                    }
                };
    }

    public void addImageToWarehouse(String key, Bitmap value)
    {       
        if(imagesWarehouse != null && imagesWarehouse.get(key) == null)
        {
            imagesWarehouse.put(key, value);
        }
    }

    public Bitmap getImageFromWarehouse(String key)
    {
        if(key != null)
        {
            return imagesWarehouse.get(key);
        }
        else
        {
            return null;
        }
    }

    public void removeImageFromWarehouse(String key)
    {
        imagesWarehouse.remove(key);
    }

    public void clearCache()
    {
        if(imagesWarehouse != null)
        {
            imagesWarehouse.evictAll();
        }       
    }

}
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{   
    private int inSampleSize = 0;

    private String imageUrl;

    private BaseAdapter adapter;

    private ImagesCache cache;

    private int desiredWidth, desiredHeight;

    private Bitmap image = null;

    private ImageView ivImageView;

    public DownloadImageTask(BaseAdapter adapter, int desiredWidth, int desiredHeight) 
    {
        this.adapter = adapter;

        this.cache = ImagesCache.getInstance();

        this.desiredWidth = desiredWidth;

        this.desiredHeight = desiredHeight;
    }

    public DownloadImageTask(ImagesCache cache, ImageView ivImageView, int desireWidth, int desireHeight)
    {
        this.cache = cache;

        this.ivImageView = ivImageView;

        this.desiredHeight = desireHeight;

        this.desiredWidth = desireWidth;
    }

    @Override
    protected Bitmap doInBackground(String... params) 
    {
        imageUrl = params[0];

        return getImage(imageUrl);
    }

    @Override
    protected void onPostExecute(Bitmap result) 
    {
        super.onPostExecute(result);

        if(result != null)
        {
            cache.addImageToWarehouse(imageUrl, result);

            if(ivImageView != null)
            {
                ivImageView.setImageBitmap(result);
            }
            else if(adapter != null)
            {
                adapter.notifyDataSetChanged();
            }
        }
    }

    private Bitmap getImage(String imageUrl)
    {   
        if(cache.getImageFromWarehouse(imageUrl) == null)
        {
            BitmapFactory.Options options = new BitmapFactory.Options();

            options.inJustDecodeBounds = true;

            options.inSampleSize = inSampleSize;

            try
            {
                URL url = new URL(imageUrl);

                HttpURLConnection connection = (HttpURLConnection)url.openConnection();

                InputStream stream = connection.getInputStream();

                image = BitmapFactory.decodeStream(stream, null, options);

                int imageWidth = options.outWidth;

                int imageHeight = options.outHeight;

                if(imageWidth > desiredWidth || imageHeight > desiredHeight)
                {   
                    System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight);

                    inSampleSize = inSampleSize + 2;

                    getImage(imageUrl);
                }
                else
                {   
                    options.inJustDecodeBounds = false;

                    connection = (HttpURLConnection)url.openConnection();

                    stream = connection.getInputStream();

                    image = BitmapFactory.decodeStream(stream, null, options);

                    return image;
                }
            }

            catch(Exception e)
            {
                Log.e("getImage", e.toString());
            }
        }

        return image;
    }
ImageView imv = (ImageView) findViewById(R.id.imageView);
ImagesCache cache = ImagesCache.getInstance();//Singleton instance handled in ImagesCache class.
cache.initializeCache();

String img = "your_image_url_here";

Bitmap bm = cache.getImageFromWarehouse(img);

if(bm != null)
{
  imv.setImageBitmap(bm);
}
else
{
  imv.setImageBitmap(null);

  DownloadImageTask imgTask = new DownloadImageTask(cache, imv, 300, 300);//Since you are using it from `Activity` call second Constructor.

  imgTask.execute(img);
}
ImageView imv = (ImageView) rowView.findViewById(R.id.imageView);
ImagesCache cache = ImagesCache.getInstance();
cache.initializeCache();

String img = "your_image_url_here";

Bitmap bm = cache.getImageFromWarehouse(img);

if(bm != null)
{
  imv.setImageBitmap(bm);
}
else
{
  imv.setImageBitmap(null);

  DownloadImageTask imgTask = new DownloadImageTask(this, 300, 300);//Since you are using it from `Adapter` call first Constructor.

  imgTask.execute(img);
}