I am making a Flutter Application where I am using Lazy Loading to load the data from server. Now, the page I have made consists of following widgets in order-
- Stack (with a button and a container)
- SizedBox (for spacing)
- SliverPagedList (to show lazy-loaded data).
Now, since the SliverPagedList is a Sliver widget I am using a CustomScrollView for the preceding widgets (Stack and SizedBox). I referred- https://pub.dev/packages/infinite_scroll_pagination/example#:~:text=Preceding/Following%20Items
The problem-
All the pages are fetched all together even when I have not reached the end of the page.
My code is-
class CategoryArticlePage extends StatefulWidget {
CategoryArticlePage({required this.category});
Category category;
@override
State<CategoryArticlePage> createState() => _CategoryArticlePageState();
}
class _CategoryArticlePageState extends State<CategoryArticlePage> {
SharedPreferences? _sharedPreferences;
final PostService _postService = PostService();
// List<posts.Post2>? _posts;
Future<void>? _loadData;
final PagingController<int, posts.Post2> _pageController =
PagingController(firstPageKey: 0);
@override
void initState() {
// _loadData = _loadArticles(); //without paging
_pageController.addPageRequestListener((pageKey) {
_loadArticles(pageKey);
});
super.initState();
}
Future<void> _loadArticles(int pageKey) async {
try {
_sharedPreferences ??= await SharedPreferences.getInstance();
final _posts = await _postService.getAllPostsForCategory(
token: _sharedPreferences!.getString(BEARER_TOKEN)!,
categoryid: widget.category.categoryId,
pageKey: pageKey,
pageSize: PAGE_SIZE);
final isLastPage = _posts.length < PAGE_SIZE;
if (isLastPage) {
_pageController.appendLastPage(_posts);
} else {
final nextPageKey = pageKey + 1;
_pageController.appendPage(_posts, nextPageKey);
}
} catch (error) {
_pageController.error = error;
}
}
@override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height -
// _appBar.preferredSize.height -
MediaQuery.of(context).padding.top -
MediaQuery.of(context).padding.bottom;
final width = MediaQuery.of(context).size.width;
return Scaffold(
body: SafeArea(
child: Consumer<CategoryProvider>(
builder: ((context, categoryProvider, child) {
return RefreshIndicator(
onRefresh: () {
return Future.sync(
() => _pageController.refresh(),
);
},
child: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Column(
children: [
Stack(
children: [
Container(
decoration: categoryTopDecoration,
padding: EdgeInsets.only(
left: 2,
right: 2,
bottom: 2,
),
alignment: Alignment.bottomLeft,
height: height * 0.4,
child: ListTile(
title: Text(
'${widget.category.categoryName}',
style: TextStyle(
fontSize: 40.sp,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
'${widget.category.categoryDescription}',
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.w700,
),
),
),
),
Positioned(
right: 10,
top: 10,
child: Padding(
padding: EdgeInsets.only(
right: 4,
),
child: OutlinedButton(
onPressed: () async {
if (categoryProvider.subscribedCategoriesIDs
.contains(widget.category.categoryId)) {
bool result = await categoryProvider
.unsubscribeFromCategory(
token: _sharedPreferences!
.getString(BEARER_TOKEN)!,
userid: _sharedPreferences!
.getInt(USER_ID)!,
categoryid:
widget.category.categoryId);
} else {
bool result = await categoryProvider
.subscribeToCategory(
token: _sharedPreferences!
.getString(BEARER_TOKEN)!,
userid: _sharedPreferences!
.getInt(USER_ID)!,
categoryid:
widget.category.categoryId);
}
},
child: (categoryProvider
.subscribedCategoriesIDs
.contains(widget.category.categoryId)
? Text('Subscribed')
: Text('Subscribe')),
),
),
),
],
),
SizedBox(
height: height * 0.02,
),
],
),
),
PagedSliverList<int, posts.Post2>.separated(
pagingController: _pageController,
builderDelegate: PagedChildBuilderDelegate<posts.Post2>(
animateTransitions: true,
// [transitionDuration] has a default value of 250 milliseconds.
transitionDuration: const Duration(milliseconds: 500),
itemBuilder: (context, item, index) {
return Padding(
padding: EdgeInsets.only(
bottom: 2,
top: 2,
),
child: GestureDetector(
onTap: () {
Get.to(() => ExploreViewArticle(
post: item,
sharedPreferences: _sharedPreferences!));
},
child: ListTile(
leading: SizedBox(
child: SizedBox(
height: 100,
width: 100,
child: CachedNetworkImage(
imageUrl:
'https://<blobstorage>/imagecontainer/${item.image}',
placeholder: (context, url) => Center(
child: Container(
height: 50,
width: 50,
child: DataLoadingIndicator(),
),
),
errorWidget: (context, url, error) =>
Image.asset(
'images/category_default.jpg'),
fit: BoxFit.cover,
),
),
),
title: Text('${item.title}'),
),
),
);
},
),
separatorBuilder: (context, index) {
return Container(
height: 2,
color: Colors.black,
);
},
),
],
),
);
}),
),
),
);
}
@override
void dispose() {
log('CategoryArticlePage dispose called');
_pageController.dispose();
super.dispose();
}
}