Flutter событие прокрутки для FutureBuilder и ListView по достижении 80% длины экрана?
У меня REST приложение которое берет с сайта постранично информацию и конвертирует в ListView список. Событие когда необходимо получить новую порцию данных срабатывает по достижении конца прокрути и выглядит так
_controller.addListener(() {
//При достижении конца прокрутки
if (_controller.position.atEdge) {
//Запрашиваю новую порцию данных
}
});
Мне хотелось, что бы данные запрашивались не в самам конце экрана, а немного раньше, что-бы пользователь не ждал загрузки новой порции данных и они подкачивались в фоне. Для этого я пробовал такой вариант
_controller.addListener(() {
//Сравниваю текущую позицию скролинга списка с максимальной минус какоё-то значение, что-бы срабатывало заранее
if (_controller.position.pixels >= _controller.position.maxScrollExtent-200) {
//Запрашиваю новую порцию данных
}
});
То есть определял текущую позицию скролинга и сравнивал с максимальной, но немного раньше, на 200 пикселей. Этот вариант не рабоатет, потому-что функция которая возвращает JSON данные работает асинхронно, а событие срабатывает множество раз и получатеся за несколько секунд 10-15 запросов, которые отрабатывает в случайном, а не строгом порядке и данные получаются вперемешку из-за этого
Пробовал вариант _controller.position.pixels == _controller.position.maxScrollExtent-200 но он совсем не работает, потому-что скролинг текущей позиции очень точный и попасть в это значение просто невозможно, событие совсем не отрабатывает. Существут ли способ, что бы можно было событие срабатывало один раз на каком-то участке списка немного заранее, до его завершения, этакий lazy loading?
Ответы (1 шт):
Должно работать как вам нужно (возможно придется доработать, когда данные загрузятся. Таймер нужно будет поставить наверное):
bool isLoading = false;
...
_controller.addListener(() async {
if (!isLoading && (_controller.position.pixels >= _controller.position.maxScrollExtent - 200)) {
isLoading = true;
await loadData().then((_) => isLoading = false); // или .whenComplete((_) => isLoading = false);
}
});