How to deal with the values taken from asynchronous methods like onComplete?

bugra.anadol :

The following method I wrote, which works fine, is in my Utils package and I call it from some of my activities.

private static Date date = null;

public static Date getCurrentTime(final Context context){

    FirebaseFunctions firebaseFunctions;
    firebaseFunctions = FirebaseFunctions.getInstance();
    firebaseFunctions.getHttpsCallable("currentTime").call()
            .addOnCompleteListener(new OnCompleteListener<HttpsCallableResult>() {
                @Override
                public void onComplete(@NonNull Task<HttpsCallableResult> task) {
                    try{
                        String dateString = task.getResult().getData().toString();
                        System.out.println("555555555555 TIME : " + dateString);
                        date =  new Date(Long.getLong(dateString));
                    }
                    catch(Exception e){
                        convertFirebaseExceptionToAlertDialog(context, "A network error");
                    }
                }
            });
    while (date == null){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    return date;
}

I want to know if there are better ways than checking the value by a loop to return a value from methods like this. (Methods that get the value will be returned from inner methods like onComplete, onSuccess)

Frank van Puffelen :

You can make something that is asynchronous work synchronously. For your code that means that your getCurrentTime can't return a Date. The code that calls getCurrentTime, will always need to be aware that it's calling a function that returns an asynchronous result.

The simplest way I usually deal with this is by defining a custom callback interface for the type:

public interface DateCallback {
  void onCallback(Date value);
}

Then you can pass a callback into getCurrentTime, which its implementation then calls when it got the current time from Cloud Functions. Something like:

public static Date getCurrentTime(final Context context, DateCallback callback){
    FirebaseFunctions firebaseFunctions;
    firebaseFunctions = FirebaseFunctions.getInstance();
    firebaseFunctions.getHttpsCallable("currentTime").call()
            .addOnCompleteListener(new OnCompleteListener<HttpsCallableResult>() {
                @Override
                public void onComplete(@NonNull Task<HttpsCallableResult> task) {
                    try{
                        String dateString = task.getResult().getData().toString();
                        System.out.println("555555555555 TIME : " + dateString);
                        callback.onCallback(new Date(Long.getLong(dateString)));
                    }
                    catch(Exception e){
                        convertFirebaseExceptionToAlertDialog(context, "A network error");
                    }
                }
            });
}

And then you'd call it with:

getCurrentTime(this, new DateCallback() {
  public void onCallback(Date value) {
    System.out.println("Current time "+value)
  }
});

Also see:

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=351923&siteId=1