JianYA JianYA - 6 months ago 33
JSON Question

Android URL images shuffle in listview

I just noticed that when I loaded my images in a listview from a url, sometimes they cycle through stuff before it settles on the right one. How can I prevent that from happening?

This is my async task from my custom adapter

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;
}
}


This is my 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;
}

Answer

Not sure if it works but maybe you can put image uri string also in the DataHandler. And check for that in the postExecute so that only when it matches the last one it applies it:

    @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);
        }
    }

And then also have a private String uri in the AsyncTask that gets set in doInBackground