ANDROID:在listView中加载异步图片 [英] ANDROID : Load asynchronous pictures in listView
问题描述
我想显示一个带有自定义适配器(带有图片和文本)的 ListView.
I 'd like to display a ListView with a customized adapter (with picture and text).
图像是从远程服务器加载的,所以我决定使用 AsyncTask.
Images are loaded from distant servers, so I have decided to use AsyncTask.
其实图片显示效果很好,但是如果我快速向下滚动,1/2秒内显示错误图片(加载后,出现正确图片)
Actually, pictures are well displayed but if I scroll down quickly, a wrong picture is displayed during 1/2 secondes (after loading, correct picture appears)
这是我的适配器代码:
public class GiAdapter extends BaseAdapter {
private Context mContext;
private List<SiteStaff> mListAppInfo;
private HashMap<Integer, ImageView> views;
private HashMap<String,Bitmap> oldPicts = new HashMap<String,Bitmap>();
private LayoutInflater mInflater;
private boolean auto;
private final String BUNDLE_URL = "url";
private final String BUNDLE_BM = "bm";
private final String BUNDLE_POS = "pos";
private final String BUNDLE_ID = "id";
public GiAdapter(Context context, List<SiteStaff> list) {
mContext = context;
mListAppInfo = list;
views = new HashMap<Integer, ImageView>();
mInflater = LayoutInflater.from(mContext);
}
@Override
public int getCount() {
return mListAppInfo.size();
}
@Override
public Object getItem(int position) {
return mListAppInfo.get(position).getId();
}
@Override
public long getItemId(int position) {
return mListAppInfo.get(position).getId();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout layoutItem;
// reuse of convertView
if (convertView == null) {
layoutItem = (LinearLayout) mInflater.inflate(R.layout.auto_gi, parent, false);
} else {
layoutItem = (LinearLayout) convertView;
}
// infos for the current element
SiteStaff entry = mListAppInfo.get(position);
//set some text fields
TextView name = (TextView) layoutItem.findViewById(R.id.name);
TextView size = (TextView) layoutItem.findViewById(R.id.size);
name.setText(entry.getName());
size.setText(entry.getSize());
// get the imageView for the current object
ImageView v = (ImageView) layoutItem.findViewById(R.id.gi_image);
// put infos in bundle and send to the LoadImage class
Bundle b = new Bundle();
//url of the pict
b.putString(BUNDLE_URL, entry.getUrl());
//position in the listView
b.putInt(BUNDLE_POS, position);
//id of the current object
b.putInt(BUNDLE_ID, entry.getId());
//put info in the map in order to display in the onPostExecute
views.put(position, v);
// thread
new LoadImage().execute(b);
return layoutItem;
}
//asyncTackClass for loadingpictures
private class LoadImage extends AsyncTask<Bundle, Void, Bundle> {
@Override
protected Bundle doInBackground(Bundle... b) {
Bitmap bm =null;
//cache: for better performance, check if url alredy exists
if(oldPicts.get(b[0].getString(BUNDLE_URL))==null){
bm = Utils.getBitMapFromUrl(b[0].getString(BUNDLE_URL));
oldPicts.put(b[0].getString(BUNDLE_URL),bm);
}else{
bm = oldPicts.get(b[0].getString(BUNDLE_URL));
}
// get info from bundle
Bundle bundle = new Bundle();
bundle.putParcelable(BUNDLE_BM, bm);
bundle.putInt(BUNDLE_POS, b[0].getInt(BUNDLE_POS));
return bundle;
}
@Override
protected void onPostExecute(Bundle result) {
super.onPostExecute(result);
//get picture saved in the map + set
ImageView view = views.get(result.getInt(BUNDLE_POS));
Bitmap bm = (Bitmap) result.getParcelable(BUNDLE_BM);
if (bm != null){ //if bitmap exists...
view.setImageBitmap(bm);
}else{ //if not picture, display the default ressource
view.setImageResource(R.drawable.unknow);
}
}
}
}
谢谢!
推荐答案
这也发生在我身上.我发现在新图像绑定到图像视图之前,旧图像会显示一段时间.在您的情况下,发生的情况是您的正确信息显示在 onPostExecute() 上,这需要一些时间,然后在显示 convertview 中设置的任何数据之前.有两种方法可以解决这个问题,
This happened to me too. What I figured out was that before the new image was getting bound to the imageview, the old one was displayed for a while. In your case, what is happening is that your correct info is showing onPostExecute(), which takes sometime, and before that whatever data was set in the convertview is being shown. There are 2 ways u could mostly fix this,
在您的 getView() 中,将 if{}... else{} 块更改为 just
In your getView(), change the if{}... else{} block to just
layoutItem = (LinearLayout) mInflater.inflate(R.layout.auto_gi, parent, false);
或
在 getView() 中使用一些占位符图像设置图像视图,直到 onPostExecute() 被调用.
set the imageview with some placeholder image in getView() till onPostExecute() is called.
希望这会有所帮助.
这篇关于ANDROID:在listView中加载异步图片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!