Android ListView 重复图片
Android ListView repeat image
我正在 android 上实现一个包含图像视图的列表视图,但我遇到了一个问题:
当一行没有图像时,它会重复前一项的图像。
这是我的适配器:
public class NewsAdapter extends BaseAdapter {
private final LayoutInflater inflater;
private final Context context;
private List<News> newsList;
public NewsAdapter(List<News> newsList, Context context) {
this.newsList = newsList;
this.context = context;
inflater = LayoutInflater.from(context);
}
...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater row = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = row.inflate(R.layout.image_new_row, null);
viewHolder = new ViewHolder();
viewHolder.mTitle = convertView.findViewById(R.id.txtNewsTitle);
viewHolder.mImage = convertView.findViewById(R.id.imageNews);
viewHolder.mDescription = convertView.findViewById(R.id.txtDescription);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
News news = newsList.get(position);
viewHolder.mTitle.setText(news.getTitle());
viewHolder.mDescription.setText(news.getDescription());
if (news.getImageUrl() != null){
ImageLoader.getInstance().displayImage(news.getImageUrl(), viewHolder.mImage);
}
else{
viewHolder.mImage.setImageResource(R.drawable.loading);
}
return convertView;
}
我的 viewHolder:
static class ViewHolder {
private TextView mTitle;
private TextView mDescription;
private ImageView mImage;
}
我的activity:
public class NewsActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
private static final String ITEM = "item";
private static final String TITLE = "title";
private static final String LINK = "link";
private static final String DESCRIPTION = "description";
private static final String MEDIA = "media:content";
private static final String IMAGE_URL = "url";
private Feed feed;
private ListView newsListView;
private ArrayList<News> newsList;
private NewsAdapter mAdapter;
private ImageLoaderConfiguration imageLoaderConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news);
newsListView = (ListView) findViewById(R.id.newsList);
this.feed = (Feed) getIntent().getSerializableExtra(Constants.EXTRA_CLICKED_FEED);
configListView();
}
private void configListView() {
File cacheDir = StorageUtils.getCacheDirectory(this);
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.loading)
.showImageOnLoading(R.drawable.loading)
.showImageOnFail(R.drawable.loading).cacheInMemory(true).cacheOnDisk(true).build();
imageLoaderConfiguration = new ImageLoaderConfiguration.Builder(this)
.defaultDisplayImageOptions(defaultOptions).build();
ImageLoader.getInstance().init(imageLoaderConfiguration);
newsList = new ArrayList<News>();
mAdapter = new NewsAdapter(newsList, this);
newsListView.setAdapter(mAdapter);
newsListView.setOnItemClickListener(this);
new RssAsyncTask().execute(
feed.getUrl());
}
private List<News> readXML(InputStream is) {
List<News> newsList =
new ArrayList<News>();
try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder =
factory.newDocumentBuilder();
Document xmlDocument = builder.parse(is);
NodeList posts =
xmlDocument.getElementsByTagName(ITEM);
String title = null, description = null,
link = null, image = null;
for (int i = 0; i < posts.getLength(); i++) {
Node post = posts.item(i);
// Cada nó ITEM tem os filhos:
// TITLE, DESCRIPTION e LINK
NodeList postInfo = post.getChildNodes();
for (int j = 0; j < postInfo.getLength(); j++) {
Node info = postInfo.item(j);
if (TITLE.equals(info.getNodeName())) {
title = info.getTextContent();
} else if (LINK.equals(
info.getNodeName())) {
link = info.getTextContent();
} else if (DESCRIPTION.equals(
info.getNodeName())) {
description = extractText(info.getTextContent()).trim();
} else if (MEDIA.equals(
info.getNodeName())) {
image = ((Element) info).getAttribute(IMAGE_URL);
}
}
newsList.add(
new News(title, description, link, image));
}
} catch (Throwable e) {
e.printStackTrace();
}
return newsList;
}
class RssAsyncTask extends
AsyncTask<String, Void, List<News>> {
ProgressDialog dialog;
...
@Override
protected void onPostExecute(List<News> result) {
super.onPostExecute(result);
dialog.dismiss();
newsList.addAll(result);
mAdapter.notifyDataSetChanged();
}
}
}
obs:我正在使用通用图像加载 api:
https://github.com/nostra13/Android-Universal-Image-Loader
当然可以...您正在重复使用前一项的布局。这就是下面语句的意思。
viewHolder = (ViewHolder) convertView.getTag();
如果您没有在 getView
方法中对其进行初始化,它将显示与上一项相同的内容。
根据您的代码 - 图片下载失败时可能会发生这种情况。
您可以使用:
viewHolder.mImage.setImageResource(R.drawable.loading);
if (news.getImageUrl() != null){
ImageLoader.getInstance().displayImage(news.getImageUrl(), viewHolder.mImage);
}
或
您可以使用以下代码:
ImageLoader.getInstance().displayImage(imageUri, imageView, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
...
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
...
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
...
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
...
}
}
});
如下所示将您的变量初始化放入for循环中,以便它每次都将变量初始化为null..
for (int i = 0; i < posts.getLength(); i++) {
String title = null, description = null,
link = null, image = null;
Node post = posts.item(i);
// Cada nó ITEM tem os filhos:
// TITLE, DESCRIPTION e LINK
NodeList postInfo = post.getChildNodes();
for (int j = 0; j < postInfo.getLength(); j++) {
Node info = postInfo.item(j);
if (TITLE.equals(info.getNodeName())) {
title = info.getTextContent();
} else if (LINK.equals(
info.getNodeName())) {
link = info.getTextContent();
} else if (DESCRIPTION.equals(
info.getNodeName())) {
description = extractText(info.getTextContent()).trim();
} else if (MEDIA.equals(
info.getNodeName())) {
image = ((Element) info).getAttribute(IMAGE_URL);
}
}
newsList.add(
new News(title, description, link, image));
}
我正在 android 上实现一个包含图像视图的列表视图,但我遇到了一个问题: 当一行没有图像时,它会重复前一项的图像。
这是我的适配器:
public class NewsAdapter extends BaseAdapter {
private final LayoutInflater inflater;
private final Context context;
private List<News> newsList;
public NewsAdapter(List<News> newsList, Context context) {
this.newsList = newsList;
this.context = context;
inflater = LayoutInflater.from(context);
}
...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater row = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = row.inflate(R.layout.image_new_row, null);
viewHolder = new ViewHolder();
viewHolder.mTitle = convertView.findViewById(R.id.txtNewsTitle);
viewHolder.mImage = convertView.findViewById(R.id.imageNews);
viewHolder.mDescription = convertView.findViewById(R.id.txtDescription);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
News news = newsList.get(position);
viewHolder.mTitle.setText(news.getTitle());
viewHolder.mDescription.setText(news.getDescription());
if (news.getImageUrl() != null){
ImageLoader.getInstance().displayImage(news.getImageUrl(), viewHolder.mImage);
}
else{
viewHolder.mImage.setImageResource(R.drawable.loading);
}
return convertView;
}
我的 viewHolder:
static class ViewHolder {
private TextView mTitle;
private TextView mDescription;
private ImageView mImage;
}
我的activity:
public class NewsActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
private static final String ITEM = "item";
private static final String TITLE = "title";
private static final String LINK = "link";
private static final String DESCRIPTION = "description";
private static final String MEDIA = "media:content";
private static final String IMAGE_URL = "url";
private Feed feed;
private ListView newsListView;
private ArrayList<News> newsList;
private NewsAdapter mAdapter;
private ImageLoaderConfiguration imageLoaderConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news);
newsListView = (ListView) findViewById(R.id.newsList);
this.feed = (Feed) getIntent().getSerializableExtra(Constants.EXTRA_CLICKED_FEED);
configListView();
}
private void configListView() {
File cacheDir = StorageUtils.getCacheDirectory(this);
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.loading)
.showImageOnLoading(R.drawable.loading)
.showImageOnFail(R.drawable.loading).cacheInMemory(true).cacheOnDisk(true).build();
imageLoaderConfiguration = new ImageLoaderConfiguration.Builder(this)
.defaultDisplayImageOptions(defaultOptions).build();
ImageLoader.getInstance().init(imageLoaderConfiguration);
newsList = new ArrayList<News>();
mAdapter = new NewsAdapter(newsList, this);
newsListView.setAdapter(mAdapter);
newsListView.setOnItemClickListener(this);
new RssAsyncTask().execute(
feed.getUrl());
}
private List<News> readXML(InputStream is) {
List<News> newsList =
new ArrayList<News>();
try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder =
factory.newDocumentBuilder();
Document xmlDocument = builder.parse(is);
NodeList posts =
xmlDocument.getElementsByTagName(ITEM);
String title = null, description = null,
link = null, image = null;
for (int i = 0; i < posts.getLength(); i++) {
Node post = posts.item(i);
// Cada nó ITEM tem os filhos:
// TITLE, DESCRIPTION e LINK
NodeList postInfo = post.getChildNodes();
for (int j = 0; j < postInfo.getLength(); j++) {
Node info = postInfo.item(j);
if (TITLE.equals(info.getNodeName())) {
title = info.getTextContent();
} else if (LINK.equals(
info.getNodeName())) {
link = info.getTextContent();
} else if (DESCRIPTION.equals(
info.getNodeName())) {
description = extractText(info.getTextContent()).trim();
} else if (MEDIA.equals(
info.getNodeName())) {
image = ((Element) info).getAttribute(IMAGE_URL);
}
}
newsList.add(
new News(title, description, link, image));
}
} catch (Throwable e) {
e.printStackTrace();
}
return newsList;
}
class RssAsyncTask extends
AsyncTask<String, Void, List<News>> {
ProgressDialog dialog;
...
@Override
protected void onPostExecute(List<News> result) {
super.onPostExecute(result);
dialog.dismiss();
newsList.addAll(result);
mAdapter.notifyDataSetChanged();
}
}
}
obs:我正在使用通用图像加载 api: https://github.com/nostra13/Android-Universal-Image-Loader
当然可以...您正在重复使用前一项的布局。这就是下面语句的意思。
viewHolder = (ViewHolder) convertView.getTag();
如果您没有在 getView
方法中对其进行初始化,它将显示与上一项相同的内容。
根据您的代码 - 图片下载失败时可能会发生这种情况。 您可以使用:
viewHolder.mImage.setImageResource(R.drawable.loading);
if (news.getImageUrl() != null){
ImageLoader.getInstance().displayImage(news.getImageUrl(), viewHolder.mImage);
}
或
您可以使用以下代码:
ImageLoader.getInstance().displayImage(imageUri, imageView, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
...
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
...
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
...
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
...
}
}
});
如下所示将您的变量初始化放入for循环中,以便它每次都将变量初始化为null..
for (int i = 0; i < posts.getLength(); i++) {
String title = null, description = null,
link = null, image = null;
Node post = posts.item(i);
// Cada nó ITEM tem os filhos:
// TITLE, DESCRIPTION e LINK
NodeList postInfo = post.getChildNodes();
for (int j = 0; j < postInfo.getLength(); j++) {
Node info = postInfo.item(j);
if (TITLE.equals(info.getNodeName())) {
title = info.getTextContent();
} else if (LINK.equals(
info.getNodeName())) {
link = info.getTextContent();
} else if (DESCRIPTION.equals(
info.getNodeName())) {
description = extractText(info.getTextContent()).trim();
} else if (MEDIA.equals(
info.getNodeName())) {
image = ((Element) info).getAttribute(IMAGE_URL);
}
}
newsList.add(
new News(title, description, link, image));
}