를 사용하여 ListView
해당 이미지와 관련된 일부 이미지 및 캡션을 표시하고 있습니다. 인터넷에서 이미지를 가져옵니다. 텍스트가 표시되는 동안 UI가 차단되지 않고 이미지가 다운로드 될 때 이미지가 표시되도록 이미지를 지연로드하는 방법이 있습니까?
총 이미지 수는 고정되어 있지 않습니다.
를 사용하여 ListView
해당 이미지와 관련된 일부 이미지 및 캡션을 표시하고 있습니다. 인터넷에서 이미지를 가져옵니다. 텍스트가 표시되는 동안 UI가 차단되지 않고 이미지가 다운로드 될 때 이미지가 표시되도록 이미지를 지연로드하는 방법이 있습니까?
총 이미지 수는 고정되어 있지 않습니다.
답변:
내 앱이 현재 표시하고있는 이미지를 담기 위해 만든 내용은 다음과 같습니다. 여기서 사용중인 "Log"개체는 Android 내부의 최종 Log 클래스에 대한 사용자 지정 래퍼입니다.
package com.wilson.android.library;
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.IOException;
public class DrawableManager {
private final Map<String, Drawable> drawableMap;
public DrawableManager() {
drawableMap = new HashMap<String, Drawable>();
}
public Drawable fetchDrawable(String urlString) {
if (drawableMap.containsKey(urlString)) {
return drawableMap.get(urlString);
}
Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
try {
InputStream is = fetch(urlString);
Drawable drawable = Drawable.createFromStream(is, "src");
if (drawable != null) {
drawableMap.put(urlString, drawable);
Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
+ drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
+ drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
} else {
Log.w(this.getClass().getSimpleName(), "could not get thumbnail");
}
return drawable;
} catch (MalformedURLException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
}
}
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
if (drawableMap.containsKey(urlString)) {
imageView.setImageDrawable(drawableMap.get(urlString));
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
imageView.setImageDrawable((Drawable) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
//TODO : set imageView to a "pending" image
Drawable drawable = fetchDrawable(urlString);
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
};
thread.start();
}
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(urlString);
HttpResponse response = httpClient.execute(request);
return response.getEntity().getContent();
}
}
LRU Cache
developer.android.com/training/displaying-bitmaps/...
이미지 가있는 게으른 목록 (GitHub에 위치) 의 간단한 데모를 만들었습니다 .
기본 사용법
ImageLoader imageLoader=new ImageLoader(context); ... imageLoader.DisplayImage(url, imageView);
AndroidManifest.xml에 다음 권한을 추가하는 것을 잊지 마십시오.
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> Please
ImageLoader 인스턴스를 하나만 만들고 응용 프로그램 주위에서 재사용하십시오. 이 방법으로 이미지 캐싱이 훨씬 더 효율적입니다.
누군가에게 도움이 될 수 있습니다. 백그라운드 스레드에서 이미지를 다운로드합니다. 이미지가 SD 카드와 메모리에 캐시됩니다. 캐시 구현은 매우 간단하며 데모 용으로 충분합니다. inSampleSize로 이미지를 디코딩하여 메모리 소비를 줄입니다. 또한 재활용 뷰를 올바르게 처리하려고합니다.
오픈 소스 기기 Universal Image Loader를 권장 합니다. 원래 Fedor Vlasov의 프로젝트 LazyList를 기반으로하며 그 이후로 크게 개선되었습니다.
성능을위한 멀티 스레딩Gilles Debunne의 튜토리얼, .
이것은 Android 개발자 블로그에서 가져온 것입니다. 제안 된 코드는 다음을 사용합니다.
AsyncTasks
.FIFO cache
.garbage collect
캐시입니다.Drawable
당신은 다운로드하는 동안.업데이트 :이 답변은 현재 매우 효과적이지 않습니다. 가비지 콜렉터는 SoftReference 및 WeakReference에 대해 적극적으로 작동하므로이 코드는 새 앱에는 적합하지 않습니다. (대신 Universal Image Loader 와 같은 라이브러리를 사용해보십시오. 다른 답변에서 제안 된 .)
코드에 대해서는 James, SoftReference 사용에 대한 제안은 Bao-Long에게 감사드립니다. James 코드에서 SoftReference 변경 사항을 구현했습니다. 불행히도 SoftReferences로 인해 이미지가 너무 빨리 가비지 수집되었습니다. 필자의 경우 목록 크기가 제한되어 있고 이미지가 작기 때문에 SoftReference 항목이 없으면 문제가 없습니다.
1 년 전에 Google 그룹에 대한 SoftReferences에 대한 토론이 있습니다 : 링크 링크 . 너무 이른 가비지 수집에 대한 해결책으로 dalvik.system.VMRuntime.setMinimumHeapSize ()를 사용하여 VM 힙 크기를 수동으로 설정할 가능성을 제안합니다.
public DrawableManager() {
drawableMap = new HashMap<String, SoftReference<Drawable>>();
}
public Drawable fetchDrawable(String urlString) {
SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
if (drawableRef != null) {
Drawable drawable = drawableRef.get();
if (drawable != null)
return drawable;
// Reference has expired so remove the key from drawableMap
drawableMap.remove(urlString);
}
if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
try {
InputStream is = fetch(urlString);
Drawable drawable = Drawable.createFromStream(is, "src");
drawableRef = new SoftReference<Drawable>(drawable);
drawableMap.put(urlString, drawableRef);
if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
+ drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
+ drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
return drawableRef.get();
} catch (MalformedURLException e) {
if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
} catch (IOException e) {
if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
}
}
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
if (drawableRef != null) {
Drawable drawable = drawableRef.get();
if (drawable != null) {
imageView.setImageDrawable(drawableRef.get());
return;
}
// Reference has expired so remove the key from drawableMap
drawableMap.remove(urlString);
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
imageView.setImageDrawable((Drawable) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
//TODO : set imageView to a "pending" image
Drawable drawable = fetchDrawable(urlString);
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
};
thread.start();
}
피카소
Jake Wharton의 Picasso Library를 사용하십시오. (ActionBarSherlock 개발자의 완벽한 이미지 로딩 라이브러리)
Android 용 강력한 이미지 다운로드 및 캐싱 라이브러리.
이미지는 Android 애플리케이션에 필요한 컨텍스트와 시각적 감각을 추가합니다. Picasso는 응용 프로그램에서 번거롭지 않은 이미지 로딩을 허용합니다. 종종 한 줄의 코드로도 가능합니다!
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
피카소는 안드로이드에서 이미지 로딩의 많은 함정을 자동으로 처리합니다.
어댑터에서 ImageView 재활용 및 다운로드 취소 처리 최소한의 메모리 사용으로 복잡한 이미지 변환. 자동 메모리 및 디스크 캐싱.
활주
글라이드는 미디어 디코딩, 메모리 및 디스크 캐싱 및 리소스 풀링을 간단하고 사용하기 쉬운 인터페이스로 감싸는 Android 용 빠르고 효율적인 오픈 소스 미디어 관리 프레임 워크입니다.
Glide는 비디오 스틸, 이미지 및 애니메이션 GIF 가져 오기, 디코딩 및 표시를 지원합니다. Glide에는 개발자가 거의 모든 네트워크 스택에 플러그인 할 수있는 유연한 API가 포함되어 있습니다. 기본적으로 Glide는 커스텀 HttpUrlConnection 기반 스택을 사용하지만 대신 Google의 Volley 프로젝트 또는 Square의 OkHttp 라이브러리에 플러그인하는 유틸리티 라이브러리도 포함합니다.
Glide.with(this).load("http://goo.gl/h8qOq7").into(imageView);
글라이드의 주요 초점은 모든 종류의 이미지 목록을 가능한 한 매끄럽고 빠르게 스크롤하는 것입니다. 그러나 글라이드는 원격 이미지를 가져 와서 크기를 조정하고 표시해야하는 거의 모든 경우에 효과적입니다.
페이스 북에 의해 프레스코
Fresco는 Android 애플리케이션에서 이미지를 표시하기위한 강력한 시스템입니다.
Fresco는 이미지 로딩 및 디스플레이를 관리하므로 사용자는 필요하지 않습니다. 네트워크, 로컬 스토리지 또는 로컬 리소스에서 이미지를로드하고 이미지가 도착할 때까지 자리 표시자를 표시합니다. 캐시에는 두 가지 레벨이 있습니다. 하나는 메모리에 있고 다른 하나는 내부 저장소에 있습니다.
Android 4.x 이하에서는 Fresco가 Android 메모리의 특수 영역에 이미지를 넣습니다. 이를 통해 응용 프로그램을 더 빠르게 실행할 수 있습니다.
고성능 로더-여기에 제안 된 방법을 검토 한 후 Ben의 솔루션 을 약간 변경하여 사용했습니다.
비트 맵을 사용하는 것보다 드로어 블을 사용하는 것이 더 빠르다는 것을 깨달았습니다.
SoftReference를 사용하는 것은 좋지만 캐시 된 이미지가 너무 자주 삭제되므로 이미지 참조가 포함 된 링크 된 목록을 추가하여 미리 정의 된 크기에 도달 할 때까지 이미지가 삭제되지 않도록합니다.
InputStream을 열려면 웹 캐시를 사용할 수있는 java.net.URLConnection을 사용했습니다 (응답 캐시를 먼저 설정해야하지만 다른 이야기입니다)
내 코드 :
import java.util.Map;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Collections;
import java.util.WeakHashMap;
import java.lang.ref.SoftReference;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import android.os.Handler;
import android.os.Message;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
public class DrawableBackgroundDownloader {
private final Map<String, SoftReference<Drawable>> mCache = new HashMap<String, SoftReference<Drawable>>();
private final LinkedList <Drawable> mChacheController = new LinkedList <Drawable> ();
private ExecutorService mThreadPool;
private final Map<ImageView, String> mImageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
public static int MAX_CACHE_SIZE = 80;
public int THREAD_POOL_SIZE = 3;
/**
* Constructor
*/
public DrawableBackgroundDownloader() {
mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
}
/**
* Clears all instance data and stops running threads
*/
public void Reset() {
ExecutorService oldThreadPool = mThreadPool;
mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
oldThreadPool.shutdownNow();
mChacheController.clear();
mCache.clear();
mImageViews.clear();
}
public void loadDrawable(final String url, final ImageView imageView,Drawable placeholder) {
mImageViews.put(imageView, url);
Drawable drawable = getDrawableFromCache(url);
// check in UI thread, so no concurrency issues
if (drawable != null) {
//Log.d(null, "Item loaded from mCache: " + url);
imageView.setImageDrawable(drawable);
} else {
imageView.setImageDrawable(placeholder);
queueJob(url, imageView, placeholder);
}
}
private Drawable getDrawableFromCache(String url) {
if (mCache.containsKey(url)) {
return mCache.get(url).get();
}
return null;
}
private synchronized void putDrawableInCache(String url,Drawable drawable) {
int chacheControllerSize = mChacheController.size();
if (chacheControllerSize > MAX_CACHE_SIZE)
mChacheController.subList(0, MAX_CACHE_SIZE/2).clear();
mChacheController.addLast(drawable);
mCache.put(url, new SoftReference<Drawable>(drawable));
}
private void queueJob(final String url, final ImageView imageView,final Drawable placeholder) {
/* Create handler in UI thread. */
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
String tag = mImageViews.get(imageView);
if (tag != null && tag.equals(url)) {
if (imageView.isShown())
if (msg.obj != null) {
imageView.setImageDrawable((Drawable) msg.obj);
} else {
imageView.setImageDrawable(placeholder);
//Log.d(null, "fail " + url);
}
}
}
};
mThreadPool.submit(new Runnable() {
@Override
public void run() {
final Drawable bmp = downloadDrawable(url);
// if the view is not visible anymore, the image will be ready for next time in cache
if (imageView.isShown())
{
Message message = Message.obtain();
message.obj = bmp;
//Log.d(null, "Item downloaded: " + url);
handler.sendMessage(message);
}
}
});
}
private Drawable downloadDrawable(String url) {
try {
InputStream is = getInputStream(url);
Drawable drawable = Drawable.createFromStream(is, url);
putDrawableInCache(url,drawable);
return drawable;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private InputStream getInputStream(String urlString) throws MalformedURLException, IOException {
URL url = new URL(urlString);
URLConnection connection;
connection = url.openConnection();
connection.setUseCaches(true);
connection.connect();
InputStream response = connection.getInputStream();
return response;
}
}
import java.util.Map; import java.util.HashMap; import java.util.LinkedList; import java.util.Collections; import java.util.WeakHashMap; import java.lang.ref.SoftReference; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import android.graphics.drawable.Drawable; import android.widget.ImageView; import android.os.Handler; import android.os.Message; import java.io.InputStream; import java.net.MalformedURLException; import java.io.IOException; import java.net.URL; import java.net.URLConnection;
나는이 안드로이드 교육을 따랐으며 메인 UI를 차단하지 않고 이미지를 다운로드하는 데 훌륭한 역할을한다고 생각합니다. 또한 많은 이미지를 통한 캐싱 및 스크롤 처리를 처리합니다. 효율적으로 큰 비트 맵로드
1. Picasso 는 응용 프로그램에서 번거롭지 않은 이미지 로딩을 허용합니다. 종종 한 줄의 코드로도 가능합니다!
Gradle 사용 :
implementation 'com.squareup.picasso:picasso:2.71828'
한 줄의 코드 만!
Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView);
2. 글라이드 부드러운 스크롤링에 중점을 둔 Android 용 이미지 로딩 및 캐싱 라이브러리
Gradle 사용 :
repositories {
mavenCentral()
google()
}
dependencies {
implementation 'com.github.bumptech.glide:glide:4.7.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
}
// 간단한보기 :
Glide.with(this).load("http://i.imgur.com/DvpvklR.png").into(imageView);
3. 프레스코 는 안드로이드 응용 프로그램에서 이미지를 표시하는 강력한 시스템입니다.
목록보기에서 이미지의 지연 로딩을 수행하는 방법을 설명하는 자습서를 작성했습니다. 재활용 및 동시성 문제에 대해 자세히 설명합니다. 또한 많은 스레드 생성을 방지하기 위해 고정 스레드 풀을 사용합니다.
내가하는 방법은 스레드를 시작하여 백그라운드에서 이미지를 다운로드하고 각 목록 항목에 대한 콜백을 전달하는 것입니다. 이미지 다운로드가 완료되면 콜백을 호출하여 목록 항목의보기를 업데이트합니다.
그러나이 방법은 뷰를 재활용 할 때 제대로 작동하지 않습니다.
XML Adapters 예제를 하나 더 추가하고 싶습니다 . Google에서 사용하고 OutOfMemory 오류를 피하기 위해 동일한 논리를 사용하고 있습니다.
기본적 으로이 ImageDownloader 는 대부분의 요구 사항을 충족하므로 귀하의 답변입니다. 일부는 그 안에 구현할 수도 있습니다.
이것은 많은 사람들이 여러 가지 방법으로 해결 한 Android의 일반적인 문제입니다. 내 생각에 가장 좋은 해결책은 Picasso 라는 비교적 새로운 라이브러리 입니다. 주요 내용은 다음과 같습니다.
Jake Wharton
의 ActionBarSherlock의 명성.ListView
감지새로운 Android Volley Library에서 NetworkImageView를 사용 com.android.volley.toolbox.NetworkImageView
하고 있으며 꽤 잘 작동하는 것 같습니다. 분명히 이것은 Google Play 및 기타 새로운 Google 응용 프로그램 에서 사용되는 것과 동일한 견해입니다 . 체크 아웃 가치가 있습니다.
인터넷에서 이미지 로딩 시간에는 많은 솔루션이 있습니다. Android-Query 라이브러리를 사용할 수도 있습니다 . 필요한 모든 활동을 제공합니다. 무엇을하고 싶은지 확인하고 라이브러리 위키 페이지를 읽으십시오. 이미지 로딩 제한을 해결하십시오.
이것은 내 코드입니다.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
ImageView imageview = (ImageView) v.findViewById(R.id.icon);
AQuery aq = new AQuery(convertView);
String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png";
aq.id(imageview).progress(this).image(imageUrl, true, true, 0, 0, new BitmapAjaxCallback() {
@Override
public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status) {
iv.setImageBitmap(bm);
}
));
return v;
}
지연 로딩 문제를 해결해야합니다.
나는이 문제가 안드로이드 개발자들 사이에서 매우 인기가 있다고 생각 하며이 문제를 해결한다고 주장하는 라이브러리가 많이 있지만 그중 소수만이 마크에있는 것 같습니다. AQuery 는 그러한 라이브러리 중 하나이지만 모든 측면에서 대부분의 라이브러리보다 낫고 시도해 볼 가치가 있습니다.
이 범용 로더를 사용하는 것이 가장 좋습니다. 지연 로딩에 많은 RnD를 수행 한 후 이것을 사용하고 있습니다.
풍모
안드로이드 2.0 이상 지원
Applidium의 경량 SDWebImage (iOS의 멋진 라이브러리) 포트 인 Android에 대한 Shutterbug를 살펴보십시오 . 비동기 캐싱을 지원하고, 실패한 URL을 저장하고, 동시성을 잘 처리하며, 유용한 서브 클래스가 포함됩니다.
풀 요청 (및 버그 보고서)도 환영합니다!
DroidParts 에는 ImageFetcher 가 있으며이를 시작하기 위해 구성이 필요 없습니다.
예를 들어 DroidPartsGram 을 복제 하십시오 .
지연 로딩 이미지에 어떤 라이브러리를 사용해야하는지 잘 모르는 사람을위한 간단한 팁 :
네 가지 기본 방법이 있습니다.
DIY => 가장 좋은 해결책은 아니지만 몇 가지 이미지와 다른 라이브러리를 사용하는 번거 로움없이 가고 싶다면
발리의 게으른 로딩 라이브러리 => 안드로이드의 사람들로부터. 그것은 훌륭하고 모든 것이지만 문서화가 잘되어 있지 않아서 사용하는 데 문제가 있습니다.
피카소 : 작동하는 간단한 솔루션으로, 가져 오려는 정확한 이미지 크기를 지정할 수도 있습니다. 사용하기 매우 간단하지만 엄청난 양의 이미지를 처리해야하는 앱의 경우 "성능"이 아닐 수도 있습니다.
UIL : 이미지를 지연로드하는 가장 좋은 방법입니다. 이미지를 캐시하고 (물론 권한이 필요함) 로더를 한 번 초기화 한 다음 작업을 수행 할 수 있습니다. 내가 지금까지 본 가장 성숙한 비동기 이미지 로딩 라이브러리.
Novoda는 또한 게으른 이미지 로딩 라이브러리를 가지고 있습니다. 있으며 Songkick, Podio, SecretDJ 및 ImageSearch와 같은 많은 앱이 라이브러리를 사용합니다.
그들의 라이브러리는 여기 Github에서 호스팅 되며 꽤 활발한 이슈 트래커 도 있습니다. 이 답변을 작성할 당시 300 개 이상의 커밋으로 프로젝트가 활발한 것으로 보입니다.
Facebook과 같은 Shimmer 레이아웃을 표시하려면 공식 Facebook 라이브러리가 있습니다. 페이스 북 쉬머 안드로이드
모든 것을 처리하므로 원하는 디자인 코드를 중첩 된 프레임에 쉬머 프레임에 넣으면됩니다. 다음은 샘플 코드입니다.
<com.facebook.shimmer.ShimmerFrameLayout
android:id=“@+id/shimmer_view_container”
android:layout_width=“wrap_content”
android:layout_height="wrap_content"
shimmer:duration="1000">
<here will be your content to display />
</com.facebook.shimmer.ShimmerFrameLayout>
그리고 여기에 대한 자바 코드가 있습니다.
ShimmerFrameLayout shimmerContainer = (ShimmerFrameLayout) findViewById(R.id.shimmer_view_container);
shimmerContainer.startShimmerAnimation();
gradle 파일에이 종속성을 추가하십시오.
implementation 'com.facebook.shimmer:shimmer:0.1.0@aar'
위의 코드는 모두 가치가 있지만 개인적인 경험으로 피카소를 사용해보십시오.
피카소 는 캐시와 다른 모든 네트워크 작업을 자동으로 관리하는이 목적을 위해 특별히 라이브러리입니다. 프로젝트에 라이브러리를 추가하고 원격 URL에서 이미지를로드하기 위해 한 줄의 코드 만 작성하면됩니다.
여기를 방문하십시오 : http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso--cms-22149
글라이드 라이브러리를 사용하십시오. 그것은 나를 위해 일했고 코드에서도 작동합니다. 이미지뿐만 아니라 gif에서도 작동합니다.
ImageView imageView = (ImageView) findViewById(R.id.test_image);
GlideDrawableImageViewTarget imagePreview = new GlideDrawableImageViewTarget(imageView);
Glide
.with(this)
.load(url)
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
})
.into(imagePreview);
}
매력처럼 작동하는 다른 방법 인 Android Query를 추천 할 수 있습니다.
여기 에서 해당 JAR 파일을 다운로드 할 수 있습니다
AQuery androidAQuery = new AQuery(this);
예로서:
androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW);
매우 빠르고 정확하며,이를 사용하면로드 할 때 애니메이션, 비트 맵 (필요한 경우) 가져 오기 등과 같은 더 많은 기능을 찾을 수 있습니다.
부여 Aquery을 시도합니다. 이미지를 비동기식으로로드하고 캐시하는 놀랍도록 간단한 방법이 있습니다.
URLImageViewHelper 는이를 수행하는 데 도움이되는 놀라운 라이브러리입니다.
public class ImageDownloader {
Map<String, Bitmap> imageCache;
public ImageDownloader() {
imageCache = new HashMap<String, Bitmap>();
}
// download function
public void download(String url, ImageView imageView) {
if (cancelPotentialDownload(url, imageView)) {
// Caching code right here
String filename = String.valueOf(url.hashCode());
File f = new File(getCacheDirectory(imageView.getContext()),
filename);
// Is the bitmap in our memory cache?
Bitmap bitmap = null;
bitmap = (Bitmap) imageCache.get(f.getPath());
if (bitmap == null) {
bitmap = BitmapFactory.decodeFile(f.getPath());
if (bitmap != null) {
imageCache.put(f.getPath(), bitmap);
}
}
// No? download it
if (bitmap == null) {
try {
BitmapDownloaderTask task = new BitmapDownloaderTask(
imageView);
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(
task);
imageView.setImageDrawable(downloadedDrawable);
task.execute(url);
} catch (Exception e) {
Log.e("Error==>", e.toString());
}
} else {
// Yes? set the image
imageView.setImageBitmap(bitmap);
}
}
}
// cancel a download (internal only)
private static boolean cancelPotentialDownload(String url,
ImageView imageView) {
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
if (bitmapDownloaderTask != null) {
String bitmapUrl = bitmapDownloaderTask.url;
if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
bitmapDownloaderTask.cancel(true);
} else {
// The same URL is already being downloaded.
return false;
}
}
return true;
}
// gets an existing download if one exists for the imageview
private static BitmapDownloaderTask getBitmapDownloaderTask(
ImageView imageView) {
if (imageView != null) {
Drawable drawable = imageView.getDrawable();
if (drawable instanceof DownloadedDrawable) {
DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
return downloadedDrawable.getBitmapDownloaderTask();
}
}
return null;
}
// our caching functions
// Find the dir to save cached images
private static File getCacheDirectory(Context context) {
String sdState = android.os.Environment.getExternalStorageState();
File cacheDir;
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = android.os.Environment.getExternalStorageDirectory();
// TODO : Change your diretcory here
cacheDir = new File(sdDir, "data/ToDo/images");
} else
cacheDir = context.getCacheDir();
if (!cacheDir.exists())
cacheDir.mkdirs();
return cacheDir;
}
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) {
}
}
}
// download asynctask
public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
private final WeakReference<ImageView> imageViewReference;
public BitmapDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {
// params comes from the execute() call: params[0] is the url.
url = (String) params[0];
return downloadBitmap(params[0]);
}
@Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
// Change bitmap only if this process is still associated with
// it
if (this == bitmapDownloaderTask) {
imageView.setImageBitmap(bitmap);
// cache the image
String filename = String.valueOf(url.hashCode());
File f = new File(
getCacheDirectory(imageView.getContext()), filename);
imageCache.put(f.getPath(), bitmap);
writeFile(bitmap, f);
}
}
}
}
static class DownloadedDrawable extends ColorDrawable {
private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
super(Color.WHITE);
bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
bitmapDownloaderTask);
}
public BitmapDownloaderTask getBitmapDownloaderTask() {
return bitmapDownloaderTaskReference.get();
}
}
// the actual download code
static Bitmap downloadBitmap(String url) {
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
HttpVersion.HTTP_1_1);
HttpClient client = new DefaultHttpClient(params);
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode
+ " while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
final Bitmap bitmap = BitmapFactory
.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// Could provide a more explicit error message for IOException or
// IllegalStateException
getRequest.abort();
Log.w("ImageDownloader", "Error while retrieving bitmap from "
+ url + e.toString());
} finally {
if (client != null) {
// client.close();
}
}
return null;
}
}
나는이 문제가 있었고 lruCache를 구현했다. API 12 이상이 필요하거나 호환성 v4 라이브러리를 사용한다고 생각합니다. lurCache는 빠른 메모리이지만 예산도 있으므로 디스크 캐시를 사용할 수 있다고 걱정되면 캐싱 비트 맵에 설명되어 있습니다.
이제 다음과 같이 어디에서나 호출 하는 싱글 톤 인 구현을 제공 할 것입니다 .
//Where the first is a string and the other is a imageview to load.
DownloadImageTask.getInstance().loadBitmap(avatarURL, iv_avatar);
다음은 웹 이미지를 검색 할 때 어댑터의 getView에서 캐시하고 호출하는 이상적인 코드입니다.
public class DownloadImageTask {
private LruCache<String, Bitmap> mMemoryCache;
/* Create a singleton class to call this from multiple classes */
private static DownloadImageTask instance = null;
public static DownloadImageTask getInstance() {
if (instance == null) {
instance = new DownloadImageTask();
}
return instance;
}
//Lock the constructor from public instances
private DownloadImageTask() {
// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in kilobytes rather than
// number of items.
return bitmap.getByteCount() / 1024;
}
};
}
public void loadBitmap(String avatarURL, ImageView imageView) {
final String imageKey = String.valueOf(avatarURL);
final Bitmap bitmap = getBitmapFromMemCache(imageKey);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
imageView.setImageResource(R.drawable.ic_launcher);
new DownloadImageTaskViaWeb(imageView).execute(avatarURL);
}
}
private void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
private Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
/* A background process that opens a http stream and decodes a web image. */
class DownloadImageTaskViaWeb extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTaskViaWeb(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon = BitmapFactory.decodeStream(in);
}
catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
addBitmapToMemoryCache(String.valueOf(urldisplay), mIcon);
return mIcon;
}
/* After decoding we update the view on the main UI. */
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
}
setUrl
하세요.