我从人们制作的一些主要缓存/图像加载方法中获取了一些内容,并提出了一些使用浏览器缓存并加载图像的方法。
我的问题是有时图像不正确(与另一个图像重复),当我向下滚动图像列表时,图像会闪烁并更改为滚动。这是我必须忍受的东西吗?
是的我为每个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:Canvas:尝试使用回收的位图android。我尝试回收时,看看.ibitmap @ 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;
}
答案 0 :(得分:3)
如果您使用ListView
,则应该意识到ListView
重新使用ImageView
个实例。如果您的加载时间过长,并且绑定到的特定ImageView已被重用于另一个Image,那么您的实现将使用旧图像覆盖正确的图像。你需要:
fetchDrawableOnThread
方法,将ImageView
标记为要提取的网址:通常您会使用setTag
并保存网址。run
方法,以确保getTag
中的ImageView
值与您刚刚提取的网址相匹配。如果它们不匹配,则ListView
已重新使用此ImageView
实例,您不应发送Message
来显示图片。在设置新的Drawable之前,你也应该在某个地方调用recycle
来清理你正在消耗的Bitmap内存,但那是一个更长的故事。
编辑:recycle
故事实际上比我记忆中的简单(我查了一些旧代码)。基本上,在您为Drawable
更新ImageView
之前,请检查它是否已设置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使用的内存,并应该有助于解决内存耗尽问题。
答案 1 :(得分:1)
基于Web视图的异步加载和缓存功能构建的快速简便的解决方案:
String htmlSnippet = "<html><head/><body>" +
"<img height=\"50px\" width=\"50px\" src=\"" + item.getImageUrl() + "\" />" +
"</body></html>";
imageWebview.loadData( htmlSnippet, "text/html", "utf-8" );