Search code examples
androidfirebaseevent-handlingpredictionfirebase-mlkit

Different Results from Event handler in Method and Outside


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;

Solution

  • 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.