我刚刚注意到,当我从 url 在列表视图中加载图像时,有时它们会在它落在正确的图像之前循环浏览内容。我怎样才能防止这种情况发生?
这是我从自定义适配器执行的异步任务
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;
}
}
这是我的视图
@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;
}
您做错了导致此问题的一件事,您将视图绑定到任务。 从理论上讲,它会导致显示图像的不一致,例如,如果您的图像视图引用到两个任务中,哪个任务最后完成都将设置位图。 如何解决此问题 只需将任务引用设置为图像视图的标签,在创建新任务之前,请先从图像视图中获取旧任务,如果它不为 null 且未完成,请取消它并创建新任务。
这是位重构代码试试这个。
@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;
}
不确定它是否有效,但也许您也可以将图像 uri 字符串也放在数据处理程序中。并在 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);
}
}
然后在 AsyncTask 中还有一个私有的字符串 uri,该 uri 在 doInBackground
中设置