我使用andorid布局来显示书籍对象,包括其名称,作者和封面图像。
然而,本书的信息可能并不完整,因此我可能需要异步加载书籍细节,一旦书籍有封面(book.icon
字段),我也需要加载图像。
例如,我第一次拿到了一本带有name
和detailLink
属性的书,所以我需要加载detailLink
的html文档,然后解析文档以填充author
icon
和description
字段等
我使用volley
库。
这是使用getView
模式的适配器的viewholder
:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.common_dynamic_book, null);
viewHolder = new ViewHolder();
viewHolder.bName = (TextView) convertView.findViewById(R.id.book_name);
viewHolder.bAuthor = (TextView) convertView.findViewById(R.id.book_author);
viewHolder.bDescriptoin = (TextView) convertView.findViewById(R.id.book_description);
viewHolder.bImage = (ImageView) convertView.findViewById(R.id.book_image);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Book bk = getItem(position);
viewHolder.book = bk;
setupViewHolder(viewHolder);
if (bk.icon == null) {
StringRequest request = new StringRequest(bk.detailLink, new Response.Listener<String>() {
@Override
public void onResponse(String content) {
new ParseTask().execute(content, finalViewHolder);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
});
queue.add(request);
}
return convertView;
}
private void setupViewHolder(final ViewHolder viewHolder) {
Book bk = viewHolder.book;
viewHolder.bName.setText(bk.name);
viewHolder.bAuthor.setText(bk.author);
if (bk.description != null) {
// viewHolder.bDescriptoin.setText(bk.description);
}
if (bk.icon != null && !bk.icon.equals("none")) {
imageLoader.get(bk.icon, new ImageLoader.ImageListener() {
@Override
public void onResponse(ImageLoader.ImageContainer imageContainer, boolean b) {
viewHolder.bImage.setImageBitmap(imageContainer.getBitmap());
}
@Override
public void onErrorResponse(VolleyError volleyError) {
}
});
}
}
class ParseTask extends AsyncTask<Object, Void, ViewHolder> {
@Override
protected ViewHolder doInBackground(Object... objects) {
String content = (String) objects[0];
ViewHolder viewHolder = (ViewHolder) objects[1];
parser.buildBook(content, viewHolder.book); //parse the html document, and fill the book object with information
return viewHolder;
}
@Override
protected void onPostExecute(ViewHolder viewHolder) {
setupViewHolder(viewHolder);
}
}
一切都很好,但我遇到了问题:
当我快速搜索列表视图时(就像一个轻松的手势),我会发现视图可能会被更新很多次。
例如,首先,适配器有10本书,其详细信息未加载。书名为Book1
Book2
.... Book10
。
然后backgournd进程将开始加载该书,一旦我从上到下推送listview,我会发现一个列表项将被多次更新。例如,它首先显示名称Book8
(没有进一步的信息),然后更改为(Book4
加载详细信息),然后可能是另一本带有加载信息的书, AND FINALLY 显示带有加载信息的Book8
。
这似乎是由视图回收引起的。我想知道是否有可能取消这个?
更新
我认为这是由视图回收引起的,例如,视图首先被绑定到Book4
,后台加载任务开始,然后当我滚动listview时,android重用此视图来显示项目Book8
,当Book4
的请求到达,并且视图更新为Book4
,然后Book8
任务完成,视图再次更新。我认为这是问题,但我不知道如何解决它......
答案 0 :(得分:0)
我强烈建议您使用Picasso library,因为它会为您自动缓存图像,并为大型图像数据集提供了很好的实现,这是您的情况!
他们的样本中也有一个类似于你应该实现的例子: SampleListDetailAdapter
希望它有所帮助!
答案 1 :(得分:0)
您需要使用ViewHolder
传递网址。
private static class ViewHolder {
// Your members
String url;
}
getView方法:
getView(..) {
Book bk = getItem(position);
viewHolder.book = bk;
// Do not recreate view if it is the same view
if (bk.icon != null && viewHolder.url != null && viewHolder.url.equals(bk.detailLink))
return convertView;
viewHolder.url = bk.detailLink;
}
当你收到回复时:
if (bk.icon != null && !bk.icon.equals("none")) {
imageLoader.get(bk.icon, new ImageLoader.ImageListener() {
@Override
public void onResponse(ImageLoader.ImageContainer imageContainer, boolean b) {
if (!imageContainer.getUrl().equals(viewHolder.url))
return;
viewHolder.bImage.setImageBitmap(imageContainer.getBitmap());
}
@Override
public void onErrorResponse(VolleyError volleyError) {
}
});
}