Android URL 图像在列表视图中随机播放



我刚刚注意到,当我从 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 中设置

最新更新