infinite_scroll_pagination
infinite_scroll_pagination copied to clipboard
Does not wait for user to scroll to end (continues loading data from API, till all the data fetched.)
I have been using this module, but there is a problem, it does not wait for the user to scroll to the end and then load the next data. It continually loads new data, until the data fetching is done. let's say I have more than 500 pages of data and par page 10, the module will continuously load all 500 pages. I used invisibleItemsThreshold. but it also not working.
final searchParams;
final PagingController<int, MovieCard> _pagingController = PagingController(firstPageKey: 1, invisibleItemsThreshold: 1,);
@override
void initState() {
_pagingController.addPageRequestListener((pageKey) =>loadNextData(pageKey));
super.initState();
}
MovieService.fetchMoviesList(endPointParams: param).then((value) {
MovieModelList movieModelList = MovieModelList.fromJson(value['movies']);
bool hasNext = value['hasNext'];
List<MovieCard> movieCardList = movieModelList.movies.map((movie) => MovieCard(movie: movie)).toList();
if (hasNext) {
_pagingController.appendPage(movieCardList, pageKey + 1);
} else {
_pagingController.appendLastPage(movieCardList);
}
}).catchError((err) {
_pagingController.error = err;
setState(() {
_hasNext = false;
});
});
}
loadNextData(int pageKey) {
const limit = 10;
if (searchParams['isRefresh'] == '1') {
searchParams['isRefresh'] = '0';
print('refreshed');
_pagingController.refresh();
}
String filterParam = 'quality=${searchParams['quality']}'
'&minimum_rating=${searchParams['rating']}'
'&genre=${searchParams['genre']}'
'&sort_by=${searchParams['sortBy']}'
'&order_by=${searchParams['orderBy']}'
'&query_term=${searchParams['searchQuery']}';
String param = 'limit=$limit&page=$pageKey&$filterParam';
print(param);
MovieService.fetchMoviesList(endPointParams: param).then((value) {
MovieModelList movieModelList = MovieModelList.fromJson(value['movies']);
bool hasNext = value['hasNext'];
List<MovieCard> movieCardList = movieModelList.movies.map((movie) => MovieCard(movie: movie)).toList();
if (hasNext) {
_pagingController.appendPage(movieCardList, pageKey + 1);
} else {
_pagingController.appendLastPage(movieCardList);
}
}).catchError((err) {
_pagingController.error = err;
setState(() {
_hasNext = false;
});
});
}
@override
void dispose() {
_pagingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return PagedGridView<int, MovieCard>(
shrinkWrap: true,
showNewPageProgressIndicatorAsGridChild: true,
showNewPageErrorIndicatorAsGridChild: true,
showNoMoreItemsIndicatorAsGridChild: true,
pagingController: _pagingController,
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(10),
addAutomaticKeepAlives: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 25.0,
childAspectRatio: (size.width / size.height / .7),
),
builderDelegate: PagedChildBuilderDelegate<MovieCard>(
itemBuilder: (context, item, index) => item,
),
);
}
Your code does not work because you are using shrinkwrap: https://api.flutter.dev/flutter/widgets/ScrollView/shrinkWrap.html which makes your entire scrollview build all its children at once and therefore breaks the way the paged view detects user scroll location. The package is working as intended.
facing the same issue right now, even without shrinkwrap: using pagedlistview.
same error here any solution
`
import '../../../../../generated/l10n.dart';
import '../../../../../injection/service_locator.dart';
import '../../../domain/entities/Product.dart';
import '../widget/product.dart';
class TopSellingProductScreen extends StatefulWidget {
const TopSellingProductScreen({Key? key}) : super(key: key);
static String path = 'top-selling';
static String name = 'top-selling';
static Page pageBuilder(BuildContext context, GoRouterState state) =>
MaterialPage(
key: state.pageKey,
child: BlocProvider.value(
value: si<ProductBloc>(),
child: const TopSellingProductScreen(),
),
);
@override
State<TopSellingProductScreen> createState() =>
_TopSellingProductScreenState();
}
class _TopSellingProductScreenState extends State<TopSellingProductScreen> {
final PagingController<int, Product> pagingController = PagingController(
firstPageKey: 1,
);
@override
void initState() {
pagingController.addPageRequestListener((pageKey) {
context.read<ProductBloc>().add(GetTopProduct(pageKey: pageKey));
});
super.initState();
}
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocListener<ProductBloc, ProductState>(
listener: (context, state) {
if (state.topProducts.isLoaded) {
final List<Product> data = state.topProducts.getDataWhenSuccess ?? [];
print('ggggggggggggggggg : ${data.length}');
final isLastPage = (data.length) < pageSize;
if (isLastPage) {
pagingController.appendLastPage(data);
} else {
final nextPageKey = state.pageKeyTopSellingProduct + data.length;
pagingController.appendPage(data, nextPageKey);
}
}
if (state.topProducts.isError) {
pagingController.error = state.topProducts.error;
}
},
child: Scaffold(
appBar: AppBar(
title: Text(s.top_selling_product),
),
body: PagedGridView(
pagingController: pagingController,
builderDelegate: PagedChildBuilderDelegate<Product>(
itemBuilder: (context, item, index) =>
ProductWidget(index: index, product: item),
),
gridDelegate: kConfigurationGrid),
),
);
}
}
`
The same problem here... Is there any solution?
I have the same problem when I tried with bloc, and with the example from raywenderlich.com, is there any solution for this? since this makes this package useless
Your code does not work because you are using shrinkwrap: https://api.flutter.dev/flutter/widgets/ScrollView/shrinkWrap.html which makes your entire scrollview build all its children at once and therefore breaks the way the paged view detects user scroll location. The package is working as intended.
Thank you man, you saved me days of debugging.
Your code does not work because you are using shrinkwrap: https://api.flutter.dev/flutter/widgets/ScrollView/shrinkWrap.html which makes your entire scrollview build all its children at once and therefore breaks the way the paged view detects user scroll location. The package is working as intended.
Thank You man.
I have the same problem, I don't know if I'm implementing something wrong but I attach an image of the widget tree I currently have. The container I have to limit the size of the view and not show the other elements, to see the effect of the scroll, but even with that I can not make the elements do not load on user demand, all elements are loaded. I have a version of flutter 2.10.5 Dart sdk 2.16.2 and I use a path management package called Modular. But I don't think that this dependency causes something, and also I tried with different versions of this package without solution (3.1.0, 3.0.0, and 2.3.0). I add the code, from my list, because I have simplified it more to avoid conflicts of other elements, but I have no success.
I already tried with PagedList and PagedList. Very possibly I am doing something wrong, but I can not visualize it.
I am bringing 2 elements per page and there are 16 elements approximately.
My code is:
class MMItemsScreen extends StatefulWidget {
const MMItemsScreen({Key? key}) : super(key: key);
@override
State<MMItemsScreen> createState() => _MMItemsScreenState();
}
class _MMItemsScreenState extends State<MMItemsScreen> {
final currentPage = 0;
final nextPage = 1;
final PagingController<int, MMProfile> _pagingController =
PagingController(firstPageKey: 1, invisibleItemsThreshold: 4);
@override
void dispose() {
super.dispose();
}
@override
void initState() {
_pagingController.addPageRequestListener((pageKey) {
getFetchItems();
});
super.initState();
}
Future<void> getFetchItems() async {
try {
final items = await _getItems(params);
final isLastPage = currentPage == nextPage; // on _getItems setting that values
if (isLastPage) {
_pagingController.appendLastPage(currentList);
} else {
_pagingController.appendPage(currentList, nextPage);
}
} catch (error) {
if (kDebugMode) {
print(error);
}
pagingController.error = error;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Merchants'),
),
body: Stack(
children: const [Container(
height: 63,
child: CustomScrollView(
slivers: [
PagedSliverList<int, MMProfile>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<MMProfile>(
itemBuilder: (context, item, index) => mMCard(item),
),
)
],
),
)],
),
);
}
}
In the last image I show my local backend with the multiple calls made one after the other, without scrolling.
If you can see something that I am doing wrong, I would appreciate it, or if you have gone through something similar, and have a solution. Thank you very much :)
** This is a simplification to not add all the code, but the operation is simulated and simplified, so some names or attributes could be wrong, because I wrote it directly, but the construction of the elements is the same and is a reference to my situation.
Another thing that happens to me in iOS is when I'm scrolling, it suddenly moves me down or up depending on the movement, that does not happen in Android.
I hope I made myself clear.