我刚刚注意到,当我从一个网址中将我的图片加载到一个列表视图中时,有时候它们会在它们正确定位之前循环显示。我该如何防止这种情况发生?
这是我自定义适配器的异步任务
private class AsyncDownloadTask extends AsyncTask<Object, String, Bitmap>{
private View view;
private Bitmap bitmap = null;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap!=null&&view!=null){
ImageView newsIcon = (ImageView)view.getTag(R.id.newsIcon);
newsIcon.setImageBitmap(bitmap);
}
}
@Override
protected Bitmap doInBackground(Object... params) {
view = (View)params[0];
String uri = (String)params[1];
try{
InputStream inputStream = new URL(uri).openStream();
bitmap = BitmapFactory.decodeStream(inputStream);
}catch (Exception e){
e.printStackTrace();
}
return bitmap;
}
}
这是我的getview
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if(position==0){
NewsObj currNews = news.get(position);
DataHandler dh;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.firstnews,parent,false);
dh = new DataHandler();
dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
row.setTag(dh);
}else{
dh = (DataHandler)row.getTag();
}
NewsObj no = (NewsObj)this.getItem(position);
row.setTag(R.id.newsIcon,row.findViewById(R.id.newsIcon));
new AsyncDownloadTask().execute(row,no.getImgurl());
dh.newsTitle.setText(no.getTitle());
dh.newsDate.setText(no.getDate());
}else{
NewsObj currNews = news.get(position);
DataHandler dh;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.newslist,parent,false);
dh = new DataHandler();
dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
row.setTag(dh);
}else{
dh = (DataHandler)row.getTag();
}
NewsObj no = (NewsObj)this.getItem(position);
row.setTag(R.id.newsIcon, row.findViewById(R.id.newsIcon));
new AsyncDownloadTask().execute(row,no.getImgurl());
dh.newsTitle.setText(no.getTitle());
dh.newsDate.setText(no.getDate());
}
return row;
}
答案 0 :(得分:3)
你做错了导致这个问题,你将你的观点绑定到任务。理论上它会导致显示图像的不一致,例如,如果您的图像视图被引用到两个任务中,那么任务完成最后一个将设置位图。如何解决此问题只需将任务引用设置为图像视图的标记,然后在创建新任务之前首先从图像视图中获取旧任务,如果它不为空且未完成取消并创建新任务。
这里是位重构代码试试这个。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
DataHandler dh;
if(position==0){
NewsObj currNews = news.get(position);
if(convertView==null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.firstnews,parent,false);
dh = new DataHandler();
dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
row.setTag(dh);
}else{
dh = (DataHandler)row.getTag();
}
NewsObj no = (NewsObj)this.getItem(position);
row.setTag(R.id.newsIcon,row.findViewById(R.id.newsIcon));
dh.newsTitle.setText(no.getTitle());
dh.newsDate.setText(no.getDate());
}else{
NewsObj currNews = news.get(position);
if(convertView==null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.newslist,parent,false);
dh = new DataHandler();
dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
row.setTag(dh);
}else{
dh = (DataHandler)row.getTag();
}
NewsObj no = (NewsObj)this.getItem(position);
row.setTag(R.id.newsIcon, row.findViewById(R.id.newsIcon));
dh.newsTitle.setText(no.getTitle());
dh.newsDate.setText(no.getDate());
}
AsyncTask task = (AsyncTask)dh.newsIcon.getTag();
if(task!=null && task.getStatus()!=FINISHED){
task.cancel();
}
task = new AsyncDownloadTask();
dh.newsIcon.setTag(task);
task.execute(row,no.getImgurl());
return row;
}
答案 1 :(得分:0)
不确定它是否有效但也许您可以将图像uri字符串也放在DataHandler中。并在postExecute中检查它,以便只有当它与最后一个匹配时才应用它:
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap!=null&&view!=null && ((DataHandler)view.getTag()).uri.equals(this.uri){
ImageView newsIcon = (ImageView)view.getTag(R.id.newsIcon);
newsIcon.setImageBitmap(bitmap);
}
}
然后在As doInBackground