Как я могу ждать метод, который не возвращает будущее? - PullRequest
1 голос
/ 21 мая 2019

Я создаю экран в приложении, используя существующий класс модели, который я не могу изменить.Модель имеет метод с именем refreshList(), который извлекает некоторые данные из API, обрабатывает их и, наконец, обновляет элемент List в модели с извлеченными данными.

Я хочу знать состояниесписок - т.е. он неинициализирован, извлекается или уже извлекается - так что я могу соответствующим образом обновить пользовательский интерфейс.

Проблема в том, что refreshList() не является async, но использует метод async для внутреннего использования.,Кроме того, внутренний метод не возвращает Future.

void refreshList(){
    if( someCondition ){
        _doRefreshList();
    }
}

void _doRefreshList() async{
    // ... do stuff 

    http.Response response = await http.get(url);

    // ... do some more stuff
}

Я хотел бы сделать что-то вроде

setState((){ _isLoading = true; });
await model.refreshList(); 
setState((){ _isLoading = false; });

, но, к сожалению, я не могу изменить методы вмодель для возврата Future.

Есть ли способ достичь этого, не изменяя refreshList() на async и возвращая Future, и не изменяя _doRefreshList() для возврата Future?

Ответы [ 3 ]

3 голосов
/ 21 мая 2019

Нет, нет способа ждать завершения асинхронной операции, если это не предоставляет какой-либо способ получить обратный вызов, когда это будет сделано.Обычный способ сделать это - вернуть будущее.Наличие параметра функции обратного вызова - это другой подход, но он редко бывает лучше, чем просто возвращать будущее.

В вашем примере refreshVerList не имеет возможности сообщить, когда это будет сделано, и ни один не сделает _doRefreshList.Вам нужно будет добавить это каким-то образом , и возвращение будущего - это самый простой и последовательный способ решения проблемы для обеих функций.

(Технически, функция _doRefreshList возвращаетбудущее, оно просто набрано как void. Вы можете привести это будущее к Future, но я решительно отговариваю такого рода махинации. Если автор функции решит вернуть что-то еще, скажем null,позднее они вполне могут делать это, поскольку тип возвращаемого значения void.)

1 голос
/ 21 мая 2019

Создайте Future со ссылкой на функцию в качестве аргумента:

Future(model.refreshList); 

Теперь вы можете использовать await, так как приведенное выше дает вам Future<void>:

setState(() { _isLoading = true; });
await Future(model.refreshList);
setState(() { _isLoading = false; });
1 голос
/ 21 мая 2019

Вы можете использовать Completer.

Completer<Null> onFetchCompleter;

 Future<Null> _doRefreshList() async{
 onFetchCompleter = Completer();
// ... do stuff 

 http.Response response = await http.get(url);

// ... do some more stuff
 onFetchCompleter.complete();

 return onFetchCompleter.future;
}

Таким же образом вы можете использовать завершитель в вашем методе refreshVerList.

...