So I have been struggling with the best way to load images in a ListView in Android for a while.
The images come from a server, so can take some time to load. From what I understand there are only 2 ways to implement this:
1 - Load the images on the main thread - This leads to have the correct images display immediately when the view displays and scrolls, but gives poor scrolling performance and can lead to the app hanging and crashing.
2 - Load the images in an AsyncTask. This means the images will be blank when the list display or scroll, but eventually display. Because of caching done by the list, you can also get the wrong image for an item. But this gives good performance and scrolling, and does not hang/crash.
Seems like neither solution works correctly. There must be a solution that works?? I have seen other posts like this, but the answer seems to always be 1 or 2, but neither is a good solution...
My code for the list adapter is below. The HttpGetImageAction.fetchImage() method either executes an async task, or fetches the image on the main thread depending on a flag I set. I also cache the images locally and on disk once they have been loaded, so the issue mainly occur the first time (but the cache is only for 100 images, and the list has 1000s)
public class ImageListAdapter extends ArrayAdapter<WebMediumConfig> {
Activity activity;
public ImageListAdapter(Activity activity, int resourceId, List<WebMediumConfig> items) {
super(activity, resourceId, items);
this.activity = activity;
}
class ImageListViewHolder {
ImageView imageView;
TextView nameView;
TextView descriptionView;
TextView statView;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageListViewHolder holder = null;
WebMediumConfig config = getItem(position);
LayoutInflater mInflater = (LayoutInflater)this.activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.image_list, null);
holder = new ImageListViewHolder();
holder.imageView = (ImageView)convertView.findViewById(R.id.imageView);
holder.nameView = (TextView) convertView.findViewById(R.id.nameView);
holder.descriptionView = (TextView)convertView.findViewById(R.id.descriptionView);
holder.statView = (TextView)convertView.findViewById(R.id.statView);
convertView.setTag(holder);
} else {
holder = (ImageListViewHolder) convertView.getTag();
}
holder.nameView.setText(Utils.stripTags(config.name));
holder.descriptionView.setText(Utils.stripTags(config.description));
holder.statView.setText(config.stats());
if (MainActivity.showImages) {
HttpGetImageAction.fetchImage(this.activity, config.avatar, holder.imageView);
} else {
holder.imageView.setVisibility(View.GONE);
}
return convertView;
}
}