Как работать со значениями, взятыми из асинхронных методов, таких как onComplete? - PullRequest
0 голосов
/ 23 марта 2020

Следующий метод, который я написал, который работает нормально, находится в моем пакете Utils, и я вызываю его из-за некоторых моих действий.

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;
}

Я хочу знать, есть ли более эффективные способы, чем проверка значения по al oop для возврата значения из методов, подобных этому. (Методы, которые получают значение, будут возвращены из внутренних методов, таких как onComplete, onSuccess)

1 Ответ

3 голосов
/ 23 марта 2020

Вы не можете заставить что-то асинхронное работать синхронно. Для вашего кода это означает, что ваш getCurrentTime не может вернуть Date. Код, который вызывает getCurrentTime, всегда должен знать, что он вызывает функцию, которая возвращает асинхронный результат.

Самый простой способ, с которым я обычно сталкиваюсь, это определение пользовательского интерфейса обратного вызова для типа:

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

Затем вы можете передать обратный вызов в getCurrentTime, который затем вызывает его реализация, когда он получает текущее время из облачных функций. Что-то вроде:

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");
                    }
                }
            });
}

И затем вы вызываете его с помощью:

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

Также смотрите:

...