我有使用EventAdapter的ListView。
public class EventAdapter extends BaseAdapter {
...
public View getView(int position, View view, ViewGroup parent) {
...
cache.imgIcon.setImageDrawable(ImgCache.setImg(url, progressBar));
...
}
ImgCache用于缓存图像的类。
public class ImgCache {
public static HashMap<String, Drawable> imgCache;
// get img from cache if exist, or download and put in cache
public static Drawable setImg(final String link, final ProgressBar progressBar) {
final Drawable[] image = {null};
if (imgCache.containsKey(link)) {
image[0] = imgCache.get(link);
progressBar.setVisibility(View.INVISIBLE);
} else {
new AsyncTask<Void, Void, Drawable>() {
@Override
protected Drawable doInBackground(Void... params) {
URL url = null;
try {
url = new URL(link);
URLConnection connection = url.openConnection();
image[0] = Drawable.createFromStream(connection.getInputStream(), "src");
} catch (Exception e) {
e.printStackTrace();
}
imgCache.put(link, image[0]);
return image[0];
}
@Override
protected void onPostExecute(Drawable result) {
progressBar.setVisibility(View.INVISIBLE);
}
}.execute();
}
return image[0];
}
}
问题是什么?
用Activity
打开ListView
后,所有图片都开始加载。但是在加载完成后它们不显示。看起来像是:
然后我尝试向下滚动2个项目然后返回上一个位置。在这个操作后,我可以看到2个带有图像的上部项目。当我滚动到它们时,所有图像也都可见。
答案 0 :(得分:2)
根据您的问题,您似乎需要在下载图像后刷新ListView
(因为当您滚动它们时会出现):
adapter.notifyDataSetChanged();
答案 1 :(得分:2)
AsyncTask是异步的,因此您应用的流程为:
需要显示ListView项目 - &gt;为List项调用Adapter.getView(...) - &gt;如果图像不在缓存中,则执行AsyncTask并返回(不等待结果) 因此,当您向下滚动并向上滚动时,将再次调用Adapter.get(...)方法,但是这次图像位于缓存中,因此它返回显示的Drawable对象
解决此问题的一种方法是从AsyncTask回调适配器,一旦检索到适配器调用notifyDataSetChanged
,就会更新映像,直接设置特定的Drawable或类似的东西(显示同时加载gif图像?)
或者
调用AsyncTask get(long timeout, TimeUnit unit)
方法,该方法将阻止man线程并等待AsyncTask完成。完成后,它将返回结果(在这种情况下你的Drawable)。这将导致主UI线程在获取图像时挂起,因此不是最佳方式。
答案 2 :(得分:1)
问题是你的视图加载并填充你的列表OnCreate,但那时你的Async任务还没有返回你的列表所以当getView调用你的缓存时它是空的,因为当你滚动它时调用android View Recycling调用getView再次,这次你的缓存已被填充。
我建议您使用onPostExecute在ListView适配器上调用NotifyDataSetChanged
,这会在您拥有图片后强制重绘。