Я создаю конструктор Listview Builder во Flutter и заполняю элементы через поставщика, который извлекает данные из firestore с разбивкой на страницы.
Итак, общий поток -
- Главный виджет получает доступ к элементам через Provider, который возвращает Future.
- Главный виджет затем создает ListView Builder, заключенный в FutureBuilder.
- Провайдер использует сервис для запроса Firestore и получает начальный набор элементов через геттер
- Поставщик затем вызывает getMoreItemsData () для получения следующего набора элементов из прослушивателя прокрутки, когда пользователь прокручивает список до конца.
Проблема, с которой я столкнулся, заключается в том, что после вызова getMoreItemsData () мой виджет позиция прокрутки сбрасывается до первого элемента, тогда как я хочу, чтобы она оставалась на последнем элементе, чтобы пользователь мог продолжить прокрутку. Я думаю, это происходит из-за notifyListeners (), который вызывается из getMoreItemsData (), но мне нужно, чтобы он обновил sh мой список элементов. Есть ли способ сделать это без сброса позиции прокрутки в начало списка?
Вот главный виджет с шагами 1 и 2:
@override
Widget build(BuildContext context) {
final itemsData = Provider.of<itemsProvider>(context);
List<item> items;
ScrollController _scrollController = new ScrollController();
return FutureBuilder(
future: itemsData.items,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Center(
child:
CircularProgressIndicator(backgroundColor: Colors.red));
} else {
if (snapshot.hasError) {
// return: show error widget
}
_scrollController
..addListener(
() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
double delta = MediaQuery.of(context).size.height * 0.30;
if (maxScroll - currentScroll <= delta) {
itemsData.getMoreitemsData();
}
},
);
items = snapshot.data ?? [];
return ListView.builder(
itemCount: items.length,
controller: _scrollController,
itemBuilder: (BuildContext context, int index) =>
Card(
margin: EdgeInsets.only(top: 10.0),
elevation: 4,
child: Text(items[index].caption),
// ... Card defined with some items
),
);
}
},
);
}
}
Вот мой фрагмент кода провайдера с шагами 3 и 4
class ItemsProvider with ChangeNotifier {
bool _getMoreData = false;
Future<List<Item>> get items async {
_items = await Service.getItems();
return _items;
}
void getMoreItemsData() {
_getMoreItems = true;
notifyListeners();
}
}
Вот мой фрагмент сервиса:
class Service {
static final firestoreInstance = Firestore.instance;
static DocumentSnapshot lastDocument, firstDocument;
static final _paginationNext = 3;
static List<Item> _itemData = [];
static Future getItems(bool getMoreData) async {
var dataFirestore;
if (!getMoreData) {
_itemData = [];
}
if (getMoreData) {
dataFirestore = await firestoreInstance
.collection("items")
.orderBy("sell", descending: true)
.startAfterDocument(lastDocument)
.limit(_paginationNext)
.getDocuments();
} else {
dataFirestore = await firestoreInstance
.collection("items")
.orderBy("sell", descending: true)
.limit(_paginationNext)
.getDocuments();
}
lastDocument =
dataFirestore.documents[dataFirestore.documents.length - 1];
dataFirestore.documents.forEach(
(doc) {
_itemData.add(Item.fromJson(doc.data));
},
);
return _itemData;
}
Вот фрагмент кода для модели Items
class Item {
String item;
String sell;
Item({
@required this.item,
@required this.sell,
// More ...
});
factory Item.fromJson(Map<dynamic, dynamic> json) {
return new Item(
item: json['item'],
sell: json['sell'],
// More ...
);
}
}