0

I'm using firebase to make predictions with my model. Results are obtained with passing event handlers to FirebaseModelInterpreter. One of the event handlers is for success case other is for failure case. I created an inner class to serve as an event handler and also it has a private field to store prediction result. When I print result to console in event handler method there is no problem, but when I try to get this result outside the result changes. I didn't understand why. Here is my code:

        // Listener for getting prediction
        class OnSuccess implements OnSuccessListener<FirebaseModelOutputs>{
            private int prediction;

            @Override
            public void onSuccess(FirebaseModelOutputs result){
                float[][] output = result.getOutput(0);
                float[] probabilities = output[0];

                //find predicted label
                int argmax = 0;
                for (int i = 1; i < probabilities.length; i++){
                    if(probabilities[i] > probabilities[argmax])
                        argmax = i;
                }
                System.out.println("Argmax is:" + argmax);
                this.prediction = argmax;
                System.out.println("After setting value:" + getPrediction());
            }

            public int getPrediction(){
                return prediction;
            }
        }

        OnSuccessListener<FirebaseModelOutputs> onSuccessEventHandler = new OnSuccess();

        modelInterpreter.run(inputs, inputOutputOptions)
                .addOnSuccessListener(onSuccessEventHandler)
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                System.out.println("Error during prediction");
                            }
                        }
                );

        int prediction = ((OnSuccess) onSuccessEventHandler).getPrediction();
        System.out.println("Before returning prediction is:"+prediction);
        return prediction;
tkarahan
  • 315
  • 1
  • 2
  • 15

1 Answers1

1

You cannot return something now that hasn't been loaded yet. With other words, you cannot simply return the prediction integer as a result of a method or simply use it outside the onSuccess() method because it will always have the initial value due the asynchronous behaviour of this method. This means that by the time you are trying to return that result or use it outside the callback, the prediction hasn't finished doing the job yet the and that's why is not accessible.

A quick solve for this problem would be to use the prediction integer only inside the onSuccess() method, otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding. Both resources are for Firebase realtime database but same rules apply in your case.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thank you. Actually I considered this because it always returned initial value, but I had no idea how to solve it. I'll look your recommendations. – tkarahan May 15 '19 at 09:46
  • Ok and keep me posted. – Alex Mamo May 15 '19 at 09:58
  • Thank you again for clarifying subject. I solved problem in this way: I created a class represents model interpreter and put configuration logic in it. Then I created an object of it in activity, configured interpreter and got interpreter object via method calls and I used run method in activity needs the result and there were no inconsistencies. – tkarahan May 15 '19 at 10:22