问题描述
我想用一个自定义的适配器(图文)显示一个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 secondes会显示一个错误的画面(加载后,正确的图片显示)
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)
下面是我的适配器的code:
Here is my adapter's code:
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);
}
}
}
}
感谢您!
推荐答案
这发生在我身上了。我想通了,是新的图像得到绑定的ImageView之前,已显示了,而旧的。在你的情况下,正在发生的事情是,你的正确的信息是显示onPostExecute(),这需要一段时间,而在这之前的任何数据集在convertview正在显示。有2种方式ü可以多为解决这一问题,
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(),改如果{} ...其他{}块只是
In your getView(), change the if{}... else{} block to just
layoutItem = (LinearLayout) mInflater.inflate(R.layout.auto_gi, parent, false);
或
设置ImageView的在getView(),直到onPostExecute()被调用一些图像占位符。
set the imageview with some placeholder image in getView() till onPostExecute() is called.
希望这有助于。
这篇关于ANDROID:加载中的ListView异步图片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!