0

I want to use Picasso to load image in webview. I found the code below. The code is work properly but if the html have many images, which will lead the UI no response a little time.

webView.setWebViewClient(new WebViewClient() {
    @SuppressWarnings("deprecation")
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        final String mime = URLConnection.guessContentTypeFromName(url);
        if (mime == null || !mime.startsWith("image")) {
            return super.shouldInterceptRequest(view, url);
        }
        try {
            final Bitmap image = Picasso.with(context).load(url).get();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            if (mime.endsWith("jpeg")) {
                image.compress(Bitmap.CompressFormat.JPEG, 100, out);
            } else if (mime.endsWith("png")) {
                image.compress(Bitmap.CompressFormat.PNG, 100, out);
            } else {
                return super.shouldInterceptRequest(view, url);
            }
            InputStream in = new ByteArrayInputStream(out.toByteArray());
            return new WebResourceResponse(mime, "UTF-8", in);
        } catch (IOException e) {
            Log.e(TAG, "Unable to load image", e);
            return super.shouldInterceptRequest(view, url);
        }
    }
});

I found the following code will lead the UI no response.

Picasso.get()

and

Bitmap.compress()

For solve UI no response problem when Picasso.get() call in WebViewClient.shouldInterceptRequest(), I use Picasso.into() to avoid thread block, but the method can’t call in WebViewClient.shouldInterceptRequest(), that will throw exception “java.lang.IllegalStateException: Method call should happen from the main thread.”

final PipedOutputStream out = new PipedOutputStream();
PipedInputStream is = new PipedInputStream(out);
NetworkUtils.getPicassoInstance(getContext())
        .load(urlStr)
        .into(new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                if (bitmap != null) {
                    try {
                        if (mime.endsWith("jpeg")) {
                            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
                        } else if (mime.endsWith("png")) {
                            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });

Because of Bitmap.compress method will waste many resource, so I use another way to convert bitmap. I use the following code to convert Bitmap to InputStream. But use this way will lead the WebView can’t show images properly, images converted by ByteBuffer will display as error image.

int byteSize = bitmap.getRowBytes() * bitmap.getHeight();
ByteBuffer byteBuffer = ByteBuffer.allocate(byteSize);
bitmap.copyPixelsToBuffer(byteBuffer);  
byte[] byteArray = byteBuffer.array();
ByteArrayInputStream bs = new ByteArrayInputStream(byteArray);

How to solve the problem? Thank you in advance.

KpSt
  • 43
  • 8
  • Can you specify the need of it ? Are you downloading a image from WebView ? Also Have a look at https://stackoverflow.com/a/8274881/4168607. – ADM Apr 06 '18 at 10:16
  • I want to use Picasso handle all of download images request in WebView. – KpSt Apr 06 '18 at 10:21
  • Ok . I Already have mentioned the reason below . I think to download some resource you need to notify user that something is downloading So you have to do this on a `Thread`. I am not sure about the problem but does `DownloadManager` fits your requirements . – ADM Apr 06 '18 at 10:23
  • Thank you for taking the time to answer. `WebViewClient.shouldInterceptRequest()` is not call on UI Thread, so I am confused why work in this method will get UI stuck. https://developer.android.com/reference/android/webkit/WebViewClient.html#shouldInterceptRequest(android.webkit.WebView,%20android.webkit.WebResourceRequest) Because of I need caching function of Picasso, I can’t use DownloadManager. – KpSt Apr 06 '18 at 11:10
  • Yeah i have gone threw the doc seems you are right . But i am confused since we have to return a type from `shouldInterceptRequest()` then i think we should go with a seperate task . Otherwise the return will get called synchronously after finishing the task. and that will take excess time . I am Not much familiar with `WebView`. – ADM Apr 06 '18 at 11:13

0 Answers0