웹에서 이미지를 다운로드 한 후 어떻게 캐시 할 수 있습니까?
답변
그리고 펀치 라인 : 시스템 캐시를 사용하십시오.
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. 누군가 나에게 캐시 관리자를 작성하기 전에 나에게 말했으면 좋겠다.
답변
connection.setUseCaches
위 의 우아한 솔루션 과 관련하여 슬프게도 추가 노력 없이는 작동하지 않습니다. ResponseCache
using 을 설치해야합니다 ResponseCache.setDefault
. 그렇지 않으면 비트 HttpURLConnection
를 자동으로 무시합니다 setUseCaches(true)
.
자세한 내용은 상단의 주석을 참조 FileResponseCache.java
하십시오.
(나는 이것을 의견에 게시 할 것이지만 분명히 충분한 업장이 없습니다.)
답변
비트 맵으로 변환 한 다음 Collection (HashMap, List 등)에 저장하거나 SDcard에 쓸 수 있습니다.
첫 번째 방법을 사용하여 애플리케이션 공간에 저장하는 경우, 숫자가 큰 경우 (위기 동안 가비지 수집 됨) 구체적 으로 java.lang.ref.SoftReference 주위를 랩핑 할 수 있습니다 . 그래도 재로드가 발생할 수 있습니다.
HashMap<String,SoftReference<Bitmap>> imageCache =
new HashMap<String,SoftReference<Bitmap>>();
SDcard에 작성하면 다시로드 할 필요가 없습니다. 단지 사용자 권한.
답변
LruCache
이미지를 효율적으로 캐시하는 데 사용 합니다. Android 개발자 사이트LruCache
에서 읽을 수 있습니다
안드로이드에서 이미지 다운로드 및 캐싱을 위해 아래 솔루션을 사용했습니다. 아래 단계를 수행 할 수 있습니다.
1 단계 :
클래스 이름 지정 ImagesCache
. 나는 사용했다Singleton object for this class
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();
}
}
}
2 단계:
캐시에서 비트 맵을 사용할 수없는 경우 사용되는 DownloadImageTask라는 다른 클래스를 여기에서 다운로드하십시오.
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;
}
3 단계 : 에서 사용하여 Activity
또는Adapter
참고 :Activity
클래스의 URL에서 이미지를로드하려는 경우 . 의 두 번째 생성자를 사용 DownloadImageTask
하지만 Adapter
첫 번째 생성자 를 사용하여 이미지를 표시 하려면 DownloadImageTask
(예를 들어 이미지가 ListView
있고 ‘어댑터’에서 이미지를 설정하는 중)
활동에서 사용 :
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);
}
노트 :
cache.initializeCache()
이 문장을 응용 프로그램의 첫 번째 활동에서 사용할 수 있습니다. 캐시를 초기화하면 ImagesCache
인스턴스를 사용하는 경우 매번 캐시를 초기화 할 필요가 없습니다 .
나는 설명을 잘하지 않지만 초보자가 캐시를 사용하는 방법 LruCache
과 사용법에 도움이되기를 바랍니다. 🙂
편집하다:
이제 일이라고 아주 유명한 라이브러리가 Picasso
와 Glide
안드로이드 응용 프로그램에서 매우 효율적으로 부하 이미지를 사용할 수 있습니다. 이 매우 간단하고 유용한 라이브러리 시도 안드로이드 피카소 와 글라이드를 들어 안드로이드 . 캐시 이미지에 대해 걱정할 필요가 없습니다.
Picasso는 응용 프로그램에서 번거롭지 않은 이미지 로딩을 허용합니다. 종종 한 줄의 코드로도 가능합니다!
피카소와 마찬가지로 글라이드는 여러 소스에서 이미지를로드하고 표시 할 수 있으며 이미지 조작시 캐싱을 관리하고 메모리에 미치는 영향을 줄입니다. 공식 Google 앱 (Google I / O 2015 용 앱 등)에서 사용되었으며 Picasso만큼 인기가 있습니다. 이 시리즈에서는 피카소보다 글라이드의 차이점과 장점을 살펴 보겠습니다.
글라이드와 피카소의 차이점에 대한 블로그를 방문 할 수도 있습니다
답변
이미지를 다운로드하여 메모리 카드에 저장하려면 다음과 같이하십시오.
//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));
매니페스트에 인터넷 권한을 추가하는 것을 잊지 마십시오.
<uses-permission android:name="android.permission.INTERNET" />
답변
droidfu의 이미지 캐시 사용을 고려할 것입니다. 인 메모리 및 디스크 기반 이미지 캐시를 모두 구현합니다. ImageCache 라이브러리를 활용하는 WebImageView도 얻을 수 있습니다.
다음은 droidfu 및 WebImageView에 대한 전체 설명입니다.
http://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadapter/
답변
SoftReferences를 사용해 보았습니다 .Android에서 너무 적극적으로 사용하여 사용하지 않아도됩니다.