-1

I need to return an object that was set in methodB(), I have tried a lot and searched also :

interface A{}
interface B{}

class Main{
  Object method(){
     Object o;

     new A(){
        methodA(){
            new B(){
                methodB(){
                    // how to use setters of o here?
                }
            }        
        }
    }

    return o;// o should contain the values set in methodB()
  }
}

My actual code

  public ImageUtil saveImagetoStorage() {
    final ImageUtil imageUtil[] = new ImageUtil[1];

    filepath.putFile(mPublishedImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onComplete(@NonNull final Task<UploadTask.TaskSnapshot> task) {

                UploadTask uploadTask = FirebaseUtil.sStorageReference.child(thumbs)
                        .child(randomName + ".jpg").putBytes(thumbData);

                uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                        String downloadthumbUri = taskSnapshot.getDownloadUrl().toString();
                        imageUtil[0]=new ImageUtil();
                        imageUtil[0].setImgUrl(downloadUri);
                        imageUtil[0].setImgThumb(downloadthumbUri);
                    }
                });
        }
    });
    return imageUtil[0];
}

Am I missing anything? Thanks in advance.

GN Reddy
  • 5
  • 1
  • 8
  • where are `methodA()` and `methodB()` from ? Abstrat from A and B ? or inteface ? – azro May 19 '18 at 21:25
  • 3
    I think `o` needs to be final: `final Object o;` – markspace May 19 '18 at 21:28
  • correct @azro, those A and B are implementations of Interfaces. – GN Reddy May 19 '18 at 21:28
  • o can be final and we can set it in methodB() @markspace, but when I return o, they are becoming null. – GN Reddy May 19 '18 at 21:34
  • Your `saveImagetoStorage` method returns *before* the `onSuccess` method executes. Also, the `onSuccess` method will be executed by another thread, so your code needs to be made thread-safe too. Re-think the sequence of events. You can't return an `ImageUtil` before the download completes, and you don't wait for completion of the `UploadTask` task. – Andreas May 19 '18 at 21:59
  • Just looking at your "actual code" I think perhaps `imageUtil[0]` is `null` because the downloading hasn't finished yet. It's asynchronous. – markspace May 19 '18 at 21:59
  • thanks @Andreas will work on those threads issue. – GN Reddy May 19 '18 at 22:07

2 Answers2

1

Disclaimer: This answer was written before "actual code" was added to the question.

You can't, because o must be effectively final, whether you declare it so or not.

One way to get around that is to change code to

Object[] o = new Object[1];

new A() {
    methodA() {
        new B() {
            methodB() {
                o[0] = ...
            }
        }
    }
}

return o[0];

Of course, that won't work either unless you actually call methodB before reaching the return o[0] statement.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • @GNReddy Define "did not work" (see [why “It’s not working” is not helpful](http://idownvotedbecau.se/itsnotworking/)). If you mean the returned value is `null`, then **(re)read the sentence at the end of the answer**. – Andreas May 19 '18 at 21:55
0

Your method needs to wait for the file upload to complete.

Since there are two asynchronous calls involved, one way to do this is to use a CompletableFuture.

public ImageUtil saveImagetoStorage() {
    final CompletableFuture<ImageUtil> futureImageUtil = new CompletableFuture<>();

    filepath.putFile(mPublishedImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onComplete(@NonNull final Task<UploadTask.TaskSnapshot> task) {

            UploadTask uploadTask = FirebaseUtil.sStorageReference.child(thumbs)
                    .child(randomName + ".jpg").putBytes(thumbData);

            uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                    String downloadthumbUri = taskSnapshot.getDownloadUrl().toString();
                    ImageUtil imageUtil = new ImageUtil();
                    imageUtil.setImgUrl(downloadUri);
                    imageUtil.setImgThumb(downloadthumbUri);
                    futureImageUtil.complete​(imageUtil); // Make imageUtil available
                }
            });
        }
    });
    return futureImageUtil.get(); // wait (potentially forever) until image available
}

You should of course never assume asynchronous operations can fail, so you need to add failure-handlers too, otherwise the get() will wait forever, since complete​(...) is never called.

Andreas
  • 154,647
  • 11
  • 152
  • 247