Listview catching plenty on scroll

Asked

Viewed 386 times

2

My Listview is crashing enough on the scroll, I tried to implement Viewholder to the Adapter but did not solve, could help me?

Adapter:

public class Adapter extends SimpleAdapter {
    private Context context;
    public LayoutInflater inflater = null;

    public Adapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
    {
        super(context, data, resource, from, to);

        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View view, ViewGroup parent) {
        ViewHolder viewHolder;

        HashMap<String, Object> data = (HashMap<String, Object>) super.getItem(position);

        if(view == null){
            view = inflater.inflate(R.layout.clientes, parent, false);

            viewHolder = new ViewHolder();

            viewHolder.thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
            viewHolder.title = (TextView)view.findViewById(R.id.title);
            viewHolder.content = (TextView)view.findViewById(R.id.content);

            view.setTag(viewHolder);
        }else{
            viewHolder = (ViewHolder)view.getTag();
        }

        try {
            viewHolder.thumbnail.setImageBitmap( new DownloadTask().execute(data.get("thumbnail").toString()).get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        viewHolder.title.setText(data.get("title").toString());
        viewHolder.content.setText(data.get("content").toString());

        return view;
    }

    static class ViewHolder{
        ImageView thumbnail;
        TextView title;
        TextView content;
    }
}

Downloadtask:

public class DownloadTask extends AsyncTask<String, Void, Bitmap> {

    @Override
    protected void onPreExecute() {}

    @Override
    protected Bitmap doInBackground(String... params) {
        Bitmap image = null;

        try {
            image = BitmapFactory.decodeStream( new URL(params[0]).openConnection().getInputStream());
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return image;
    }
}
  • Already tested with the line of new DownloadTask() commented?

  • If possible add the implementation of Downloadtask. At least its main part.

  • @Luídne, yes, without setting an image Listview works perfectly, the crashes occur only when using the Downloadtask class().

2 answers

2

I believe your problem may be this one:

viewHolder.thumbnail.setImageBitmap( new DownloadTask().execute(data.get("thumbnail").toString()).get());

I’m guessing because I’m not seeing your implementation of the Downloadtask. On Android all operations are performed on Main Thread, which is the thread of the UI. If you are doing any Bitmap operation on this thread surely your Viewholder will be very slow and may even lock the application.

EDIT: We have seen that the problem was even the Downloadtask, but now you are having problems to properly manage the cache of your Bitmaps. To not get off topic I suggest you open a new discussion and call this one off. It is suggested to analyze some solution already tested in some code, as the Universal Loader.

  • Includes Downloadtask class code.

  • 1

    I’m on the phone, so there’s no way to test it. But apparently the problem is the method itself. I think you should register a callback in your asyncTask to return the result to your Adapter and in the meantime use a "stub" image. Anything helped you tomorrow. You tell me. Abs

2


The problem is that the method get() of Asynctask only returns when the method doInBackground() end. You are using the Asynctask synchronously.

Change the class Downloadtask in order to receive the viewHolder.thumbnail and do the setImageBitmap() in the method onPostExecute().

public class DownloadTask extends AsyncTask<String, Void, Bitmap> {
    private final WeakReference<ImageView> imageView;

    public DownloadTask(ImageView thumbnail) {
        imageView = new WeakReference<ImageView>(thumbnail);
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        Bitmap image = null;

        try {
            image = BitmapFactory.decodeStream( new URL(params[0]).openConnection().getInputStream());
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return image;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {

        ImageView thumbnail = imageView.get();
        if (thumbnail != null) {
            if (bitmap != null) {
                thumbnail.setImageBitmap(bitmap);
            }
        }
    }
}

In the Adapter change the line

viewHolder.thumbnail.setImageBitmap(new DownloadTask()
                       .execute(data.get("thumbnail").toString()).get());

for

new DownloadTask(viewHolder.thumbnail).execute(data.get("thumbnail").toString());
  • The performance really improved, but when I scroll on the screen all the items in my list stay with the thumbnails changing as if it were a slider, this occurs when I use the Setimagebitmap function inside Asynctask.

  • This is the expected behavior. As the reading of thumbnails is asynchronous, Listview does not lock, but the images will only be shown once they are loaded one by one. Do not forget that the loading of an image, of a url, is a lengthy process.

  • One way to minimize this effect is to use a cache to save images after they have been downloaded. Whenever Listview need to display an image, the class Downloadtask first check if it exists in the cache, preventing it from being downloaded again.

  • The problem is that all positions in Listview seem to assume the same thumbnail when I scroll, each position is changing from Thumb as if it were a slidershow of images. I’ll try to record a video of what happens.

  • Video: https://vid.me/u1Oc, note that the images are repeated and sometimes exchanged in the same position.

  • 1

    Ramaral answered your initial question very well. I suggest you open another topic with the question about the cache. So we can help more people and better organize the answers. abs

  • The images are repeated because you are reusing the Views via viewHolder. The solution is, before new DownloadTask(viewHolder.thumbnail) show, in the pictureView, a Progressbar. See here an example.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.