Currently I face the followi开发者_如何学Gong issue - I create a custom ListView (1 x ImageView + 2 x TextView). It displays content from I-net, which is an XML file.
What am I doing - I'm using AsyncTask to run in background the process of downloading the XML content and filling up the ListView by calling publishProgress(...) method for each and every list item from doInBackground(...) method. When the doInBackground(...) completes I already had collected the URL of each and every image I want to display and then from onPostExecute(...) method I start download process for the images and update the UI for every downloaded image. The problem for me is that the ListView should fill up at least a few items before to start download an drawable file and update the list. Currently the ListView shows a single item and when fill next one, all images are already downloaded. I debug the app and I saw that one I stop in onPostExecute(...) method and want to take the number of ListView items, it's return just one, as it displays.
Is there a way to force appearance Listview's items, before to start the download or this because the I-net connection, that I have, is gut enough and there is not delay by downloading the images.
I forget only to mention that each and every image is not bigger then a 10KB.
This is my custom AsyncTask:
private class DownloadFilesTask extends AsyncTask<String, Object, List<RSSItem>> {
protected void onPreExecute() {
super.onPreExecute();
la.clear();
}
protected List<RSSItem> doInBackground(String... urls) {
parse(urls[0]);
if (feed == null) { return null; }
rssList = feed.getAllItems();
Iterator<RSSItem> iterator = rssList.iterator();
while(iterator.hasNext()) {
if (isCancelled()) return null;
RSSItem rss = iterator.next();
publishProgress(rss);
}
return rssList;
}
protected void onProgressUpdate(Object... progress) {
super.onProgressUpdate(progress);
la.add((RSSItem)progress[0]);
la.notifyDataSetChanged();
}
protected void onPostExecute(List<RSSItem> result) {
super.onPostExecute(result);
Drawable downloadedImage;
for (int z = 0; z < rssList.size(); z++) {
downloadedImage = downloadImage(rssList.get(z).getImageURL());
((RSSItem)rssList.get(z)).setImage(downloadedImage);
la.notifyDataSetChanged();
}
}
protected void onCancelled() {
super.onCancelled();
}
}
Here is the custom Listadapter:
private class ListAdapter extends ArrayAdapter<RSSItem> {
private List<RSSItem> items;
public ListAdapter(Context context, int textViewResourceId, List<RSSItem> items) {
super(context, textViewResourceId, items);
this.items = items;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.list_item, null);
}
RSSItem item = items.get(position);
if (item != null) {
ImageView itemImage = (ImageView) v.findViewById(R.id.ivImage);
TextView title = (TextView) v.findViewById(R.id.tvTitle);
TextView description = (TextView) v.findViewById(R.id.tvDescription);
if (item.getImage() != null) {
itemImage.setBackgroundDrawable(item.getImage());
} else {
itemImage.setBackgroundDrawable(getResources().getDrawable(R.drawable.icon));
}
if (title != null) {
title.setText(item.getTitle());
}
if (description != null) {
description.setText(item.getDescription());
}
}
return v;
}
}
...and the Item class:
public class RSSItem {
private String data = null;
private String description = null;
private Drawable image = null;
private String imageUrl = null;
private String title = null;
RSSItem() {
}
public void setData(String data) {
this.data = data;
}
public void setDescription(String description) {
this.description = description;
}
public void setImageURL(String imageURL) {
this.imageUrl = imageURL;
}
public void setImage(Drawable image) {
this.image = image;
}
public void setTitle(String title) {
this.title = title;
}
public String getData() {
return data;
}
public String getDescription() {
return description;
}
public Drawable getImage() {
return image;
}
public String getImageURL() {
return imageUrl;
}
public String getTitle() {
return title;
}
}
@MODIFICATIONS:
private class DownloadFilesTask extends AsyncTask> { protected void onPreExecute() { super.onPreExecute();
la.clear();
}
protected List<RSSItem> doInBackground(String... urls) {
parse(urls[0]);
if (feed == null) { return null; }
rssList = feed.getAllItems();
publishProgress(true);
Drawable downloadedImage;
for (int z = 0; z < rssList.size(); z++) {
downloadedImage = downloadImage(rssList.get(z).getImageURL());
((RSSItem)rssList.get(z)).setImage(downloadedImage);
}
return rssList;
}
protected void onProgressUpdate(Object... progress) {
super.onProgressUpdate(progress);
la.notifyDataSetChanged();
}
protected void onPostExecute(List<RSSItem> result) {
super.onPostExecute(result);
la.notifyDataSetChanged();
}
protected void onCancelled() {
super.onCancelled();
}
}
I'm not sure I understand your issue, but what I would do is the following (if I got it right):
I suppose you have a custom Object that you store in your ListView, let's say CustomItem.
I would place the download of the URL Image in the constructor of that object, and store the Drawable
as a member of your CustomItem. And just after you have created a new CustomItem
and got the image for it, publishProgress()
and call notifyDataSetChanged()
on your list adapter.
EDIT: You should move the code from the onPostExecute()
method at the end of your doInBackground()
method.
Try this:
private class DownloadFilesTask extends AsyncTask<String, RSSItem, Void> {
protected void onPreExecute() {
super.onPreExecute();
la.clear();
}
protected List<RSSItem> doInBackground(String... urls) {
parse(urls[0]);
if (feed == null) { return null; }
rssList = feed.getAllItems();
Iterator<RSSItem> iterator = rssList.iterator();
while(iterator.hasNext()) {
if (isCancelled()) return null;
RSSItem rss = iterator.next();
//this happens fast no need to do this
publishProgress(rss);
//la.add(rss);
}
Drawable downloadedImage;
for (int z = 0; z < rssList.size(); z++) {
downloadedImage = downloadImage(rssList.get(z).getImageURL());
((RSSItem)rssList.get(z)).setImage(downloadedImage);
publishProgress(null);
}
return rssList;
}
protected void onProgressUpdate(RSSItem... progress) {
super.onProgressUpdate(progress);
if progress!=null
la.add((RSSItem)progress[0]);
la.notifyDataSetChanged();
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
protected void onCancelled() {
super.onCancelled();
}
}
Are you populating the underlying data set of your list adapter in doInBackground()
? Then, in addition to calling publishProgress()
, you need to call adapter.notifyDataSetChanged()
in the onProgressUpdate()
of your AsyncTask
.
精彩评论