Search code examples
javaandroidjsoup

Jsoup speed very slow in reading images


I want to download images from the website and display them in the list but the speed of the downloading is very slow I assume there is a problem in my code.

private class mAsyncTask extends AsyncTask {

    Bitmap bitmap;

    @Override
    protected Void doInBackground(Void... params) {

        try {
            // Connect to the web site
            Document document = Jsoup.connect(url).get();
            // Using Elements to get the class data
            Elements mElementDataSize1 = document.select("h5");
            for (int i = 0; i < mElementDataSize1.size(); i++) {
                Elements img = document.select("[class=product_list grid row] img[src]").eq(i);
                // Locate the src attribute
                String imgSrc = img.attr("src");
                // Download image from URL
                InputStream input = new java.net.URL(imgSrc).openStream();
                // Decode Bitmap
                bitmap = BitmapFactory.decodeStream(input);

                bitmapArray.add(bitmap); // Add a bitmap
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }


    @Override
    protected void onPostExecute(Void result) {

        RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        mAdapter mDataAdapter = new mAdapter(MainActivity.this,bitmapArray);
        RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(), 2);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mDataAdapter);

    }
}

Solution

  • It's because you're trying to decode the image source to bitmap each times you found the src with:

    InputStream input = new java.net.URL(imgSrc).openStream();
    // Decode Bitmap
    bitmap = BitmapFactory.decodeStream(input);
    

    decoding an input stream into a bitmap is an expensive process and slow.

    And then you'll always waiting and accumulated the time needed to decode an image for all the images in:

    for (int i = 0; i < mElementDataSize1.size(); i++) {
    
        ...
        String imgSrc = img.attr("src");
    
        // You accumulate the the time needed to decode the image here.
        bitmap = BitmapFactory.decodeStream(input);
        ...
    }
    

    To solve the problem, you need to only save the images url and decode them later with something like this:

    // save the images url instead of the Bitmap.
    private List<String> mImageUrls = new ArrayList<>();
    
    @Override
    protected Void doInBackground(Void... params) {
        try {
    
            // Connect to the web site
            Document document = Jsoup.connect(url).get();
            // Using Elements to get the class data
            Elements mElementDataSize1 = document.select("h5");
            for (int i = 0; i < mElementDataSize1.size(); i++) {
                Elements img = document.select("[class=product_list grid row] img[src]").eq(i);
                // Locate the src attribute
                String imgSrc = img.attr("src");
    
                // add the url
                mImageUrls.add(imgSrc);
            }
    
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return v;
    }
    

    then use Glide or Picasso or etc to decode the images in your RecyclerView Adapter.