Android Picasso: Method call should happen from the main thread

I am trying to get info from a server, including photos. I have created a class called ServerManager, which allows me to download the desired information. However, I cannot download images with Picasso because I get a java.lang.IllegalStateException: Method call should happen from the main thread..

This is what I am doing in ServerManager:

// Check if the photo is already downloaded
if (!checkInternalPhoto(member)) {
    final String outputURL = context.getFilesDir().getAbsolutePath() + "/" + member.photoPath;
    String photoURL = rootURL + "photos/" + member.photoPath;
    Picasso.with(context)
            .load(photoURL)
            .into(new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    File file = new File(outputURL);
                    try {
                        file.createNewFile();
                        FileOutputStream outputStream = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
                        outputStream.flush();
                        outputStream.close();
                    } catch (IOException e) {
                        Log.e("IOException",e.getLocalizedMessage());
                    }
                }
                @Override
                public void onBitmapFailed(Drawable errorDrawable) {
                }
                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                }
    });
}

What can I do?

Edit: I tried to use the code in my MainActivity and I am getting the same error message...

 public void downloadPhotos(List<Member> memberList){
    String rootInURL = serverManager.getRootURL();
    String rootOutURL = serverManager.getOutputURL();
    for(int i = 0; i < memberList.size(); i++){
        if(!serverManager.checkInternalPhoto(memberList.get(i))){
            final String outputURL = rootOutURL + memberList.get(i).photoPath;
            String photoURL = rootInURL + "photos/" + memberList.get(i).photoPath;
            Picasso.with(this)
                    .load(photoURL)
                    .into(new Target() {
                        @Override
                        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                            File file = new File(outputURL);
                            try{
                                file.createNewFile();
                                FileOutputStream outputStream = new FileOutputStream(file);
                                bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
                                outputStream.flush();
                                outputStream.close();
                                Toast.makeText(context, "YEpa: " ,Toast.LENGTH_LONG).show();
                            } catch (IOException e){
                                Toast.makeText(context, "Error: " + e.toString(),Toast.LENGTH_LONG).show();
                            }
                        }

                        @Override
                        public void onBitmapFailed(Drawable errorDrawable) {

                        }

                        @Override
                        public void onPrepareLoad(Drawable placeHolderDrawable) {

                        }
                    });
        }
    }
}

Upvotes: 1

Views: 3102

Answers (2)

Sup.Ia
Sup.Ia

Reputation: 317

Try this and your error should disappear. This problem always happens when you use it in Unit Android test

kotlin code

 Handler(Looper.getMainLooper()).post {
 }

java code

new Handler(Looper.getMainLooper()).post(() -> {
});

Upvotes: 3

jbarat
jbarat

Reputation: 2460

You can't update an ui element from a different thread than the one which created that ui element. On Android that almost always means the main thread.

What you need to do is send back the photoUrl String to your activity or fragment on the main thread. The traditional way of doing it is by using a Handler. You can read about this more here: https://developer.android.com/training/multiple-threads/communicate-ui.html

Upvotes: 2

Related Questions