BaseAdapter 和毕加索问题
Posted
技术标签:
【中文标题】BaseAdapter 和毕加索问题【英文标题】:BaseAdapter and Picasso issue 【发布时间】:2015-04-01 06:35:57 【问题描述】:我在使用 Picasso 从服务器加载 ListView 中的图像时遇到问题。
我有一个用于填充我的 ListView 的 BaseAdapter。在这个 ListView 中,有些项目有图片,有些没有。
在这个方法中:
public View getView(final int position, View convertView, ViewGroup parent)
我愿意:
...
//context = Activity context;
//context1 = Context context1;
context1 = context.getApplicationContext();
if (!photo[position].equals(""))
String stringurl = "http://www.blablabla.it/img/"+photo[position]+".jpg";
Picasso.with(context1)
.load(stringurl)
.placeholder(R.drawable.white)
.into(holder.imageD);
else
holder.imageD.setImageBitmap(null);
此代码有效,但我经常看到图像位于与其所属位置不同的位置!
您可以想象这对用户来说非常烦人.. 谢谢大家
【问题讨论】:
您还应该在 else 语句中使用 Picasso 调用...然后应该取消对holder.imageD
的任何加载请求...
@Selvin 所以我应该写: holder.imageD.setImageBitmap(null);如果(...)毕加索...?可以举个例子吗?
else Picasso.with(context1) .load(null) .placeholder(R.drawable.white) .into(holder.imageD);
@Selvin 写:else holder.imageD.setImageBitmap(null); 不是一回事吗?
不!你看我的评论了吗?
【参考方案1】:
您遇到过这个问题,因为 ListView 回收项目视图 + Picasso 调用是异步的......它怎么会出现?
-
你开始用毕加索加载
视图被重用(convertView != null)
您正在设置
holder.imageD.setImageBitmap(null);
从第 1 点异步完成。
这就是为什么您加载了错误的图像...
为避免此类行为,您需要通知 Picasso 加载程序取消先前的请求。 因此,只需将图像位图设置为 null,您必须通过 Picasso 库进行设置(在 else 语句中使用):
Picasso.with(context1).load(null).placeholder(R.drawable.white).into(holder.imageD);
编辑:遵循@Budius cmets:更好的解决方案将是取消并设置,例如:
Picasso.with(context1).cancelRequest(holder.imageD);
//holder.imageD.setImageBitmap(null); //or
holder.imageD.setImageResource(R.drawable.white); //depends on your needs
这应该是更有效的方式,因为它应该在每次 getView 调用时创建更少的内部对象。
【讨论】:
我认为最好手动将图像设置为 null 并通知 Picasso 取消请求Picasso.with(c).cancelRequest(holder.imageD); holder.imageD.setImageBitmap(null);
您的方式似乎是无缘无故地创建新请求。
@Budius ...“新请求”是什么意思? (来自 piccasso 库的请求对象或一些网络请求?)事实上,它与“into”中的代码几乎相同:if (!data.hasImage()) picasso.cancelRequest(target); target.onPrepareLoad(setPlaceholder ? getPlaceholderDrawable() : null); return;
,如果 uri 为 null,则 hasImage 返回 false ...所以不会有网络使用的操作(如果事实上,它将是同步调用)......我的版本也将使用占位符代替空位图
我的意思是库中的 new RequestCreator
对象。从源代码行#293 if (path == null) return new RequestCreator(this, null, 0);
和行#569 上的private void cancelExistingRequest(Object target)
代码简单地取消现有的。我知道这些很小,但想象一下滚动数千个项目的列表和 GC 必须运行以删除所有这些小对象。关于占位符:也可以在 ImageView 上调用setImageResource(R....)
(来源:github.com/square/picasso/blob/master/picasso/src/main/java/com/…)
好的 ...我已将您的 cmets 添加到答案中...仍然想知道占位符是否以某种方式缓存...并且 android 框架是否正在缓存 setImageResource
...如果答案是肯定的不,那么第一个版本可能会更有效:)以上是关于BaseAdapter 和毕加索问题的主要内容,如果未能解决你的问题,请参考以下文章
[完成]notifyDataSetChanged() 不会自动更新 ListActivity
Fragment和BaseAdapter之间的Android通信
自定义BaseAdapter如何重写getItem和getItemId