[英]Multithreaded cached imageView loading
我从人们制作的一些主要缓存/图像加载方法中摘录了一部分,并提出了一些使用浏览器缓存并非常快速地加载图像的方法。
我的问题是,有时图像不正确(与另一个图像重复),当我向下滚动imageViews列表时,图像闪烁并随着滚动而变化。 这是我必须忍受的吗?
是的,我为每个imageView创建一个新线程。 我在队列中尝试了一个线程,因此加载时间太长。 即使它们都是单独的线程,也不应使用错误的drawable加载imageView。
这是我的代码。
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
if (imageView != null && urlString != null && urlString.length() > 0)
{
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
imageView.setImageDrawable((Drawable) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
if (imageView != null && urlString != null && !urlString.equals(""))
{
URL url;
try {
InputStream is = fetch(urlString);
if (is != null) {
Drawable drawable = Drawable.createFromStream((InputStream)is, "src");
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
}
catch (MalformedURLException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
}
}
}
};
thread.start();
}
}
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
if (urlString != null)
{
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (response instanceof InputStream) {
return (InputStream) response;
}
}
return null;
}
* 编辑 ***
毕竟所有评论都是我的代码:我目前正在获取05-19 00:16:49.535:ERROR / AndroidRuntime(12213):java.lang.RuntimeException:画布:尝试使用回收的位图android.graphics.Bitmap @ 4070dab0尝试回收时。
另外,当我没有进行回收时,除了看到图像仍然闪烁外,其他所有操作都有效。 甚至有时会显示错误的图像。
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
if (imageView != null && urlString != null && urlString.length() > 0)
{
imageView.setTag(urlString);
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
Drawable d = imageView.getDrawable();
if(d != null){
((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();
imageView.setImageBitmap(null);
}
imageView.setImageDrawable((Drawable) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
if (imageView != null && urlString != null && !urlString.equals(""))
{
URL url;
try {
if (imageView.getTag().equals(urlString))
{
InputStream is = fetch(urlString);
if (is != null) {
Drawable drawable = Drawable.createFromStream((InputStream)is, "src");
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
}
}
catch (MalformedURLException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
}
}
}
};
thread.start();
}
}
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
if (urlString != null)
{
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (response instanceof InputStream) {
return (InputStream) response;
}
}
return null;
}
如果您使用的是ListView
,则应该意识到ListView
重用了ImageView
实例。 如果加载时间太长,并且与之绑定的特定ImageView已重新用于另一个Image,则您的实现将用旧图像覆盖正确的图像。 你需要:
fetchDrawableOnThread
方法以将ImageView
标记为要获取的URL:通常,您将使用setTag
并保存url。 run
方法,以确保ImageView
中的getTag
值与您刚获取的url匹配。 如果它们不匹配,则ListView
将重用此ImageView
实例,并且您不应该发送Message
来显示图像。 在设置新的Drawable之前,您可能还应该在某个地方调用recycle
来清理消耗的位图内存,但这是一个更长的故事。
编辑: recycle
故事实际上比我记得的要简单(我查了一些旧代码)。 基本上,在更新ImageView
的Drawable
之前,请检查它是否已经有一个Drawable
集,以及是否确实对其调用了recycle
。 所以像这样:
ImageView iv = getImageView(); // fetch the image view somehow before you set it;
Drawable d = iv.getDrawable();
if(d != null){
((BitmapDrawable)iv.getDrawable()).getBitmap().recycle();
iv.setImageBitmap(null);
}
这将回收以前的Drawable使用的内存,并且应该有助于解决内存耗尽问题。
基于Web视图的异步加载和缓存功能的快速简便的解决方案:
String htmlSnippet = "<html><head/><body>" +
"<img height=\"50px\" width=\"50px\" src=\"" + item.getImageUrl() + "\" />" +
"</body></html>";
imageWebview.loadData( htmlSnippet, "text/html", "utf-8" );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.