'problem with getting next page data using api flutter
hey guys i got a small problem .
i made a program that shows some films from api , but the api has pages so i made a scroll controller and all things work fine .
but when i reach the end of the list and the program loads more it travelles me to the start of the page.
i tried to use the infinite scroll pagination package but there is no videos explaining it so i couldnt use it . this is my code .
import 'dart:async';
import 'package:MyCima/models/films_data_model.dart';
import 'package:MyCima/services/services.dart';
import 'package:flutter/material.dart';
import '../../constants.dart';
import 'films_card.dart';
class ShowsListDesign extends StatefulWidget {
final String filterName;
const ShowsListDesign(this.filterName, {Key? key}) : super(key: key);
@override
_ShowsListDesignState createState() => _ShowsListDesignState();
}
class _ShowsListDesignState extends State<ShowsListDesign> {
ScrollController controller = ScrollController();
ServicesClass service = ServicesClass();
FilmsDataModel modelClass = FilmsDataModel();
late Future<List> filmsFutureList;
int pageNumber = 1;
@override
void initState() {
super.initState();
if(pageNumber == 1) {
filmsFutureList = getFilmsList();
}
controller.addListener(listenScrolling);
}
@override
void dispose() {
controller.removeListener(listenScrolling);
controller.dispose();
super.dispose();
}
Future<List> getFilmsList()async {
return await service.getFilms('posts/$pageNumber/${widget.filterName}') ;
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: filmsFutureList,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
switch (snapshot.connectionState) {
case ConnectionState.active:
case ConnectionState.waiting:
return const Center(
child: CircularProgressIndicator(),
);
case ConnectionState.done:
return Stack(
alignment: Alignment.bottomCenter,
children: [
GridView.builder(
itemCount: snapshot.data.length,
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 250,
crossAxisSpacing: 24,
mainAxisSpacing: 24,
childAspectRatio: (2 / 3),
),
controller: controller,
itemBuilder: (context, index) {
modelClass =
FilmsDataModel.fromJson(snapshot.data[index]);
return FilmsCard(
image: modelClass.thumbUrl,
title: modelClass.title,
year: modelClass.year,
);
},
),
FloatingActionButton(
onPressed: () {
scrollUp();
},
elevation: 24,
backgroundColor: PRIMARY,
child: const Text(
'Scroll Up',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
),
),
),
],
);
case ConnectionState.none:
return const Center(
child: Text('No Connection'),
);
}
} else {
return const Center(child: CircularProgressIndicator());
}
},
);
}
void scrollUp() {
const double start = 0;
controller.animateTo(start,
duration: const Duration(seconds: 1, milliseconds: 50),
curve: Curves.easeIn);
}
void listenScrolling() {
if (controller.position.atEdge) {
final isTop = controller.position.pixels == 0;
if (isTop) {
//refresh method
} else {
getNxtPageData();
}
}
}
Future<void> getNxtPageData() async{
pageNumber++;
filmsFutureList = getFilmsList();
setState(() {});
}
}
Solution 1:[1]
Because you are using setState((){}) and it rebuilds the widget, it takes back it to the top of the screen. You should add ValueKey with your FilmsCard(). Please keep in mind that ValueKey must be unique.
GridView.builder(
itemCount: snapshot.data.length,
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 250,
crossAxisSpacing: 24,
mainAxisSpacing: 24,
childAspectRatio: (2 / 3),
),
controller: controller,
itemBuilder: (context, index) {
modelClass =
FilmsDataModel.fromJson(snapshot.data[index]);
return FilmsCard(
key: Valuekey(modelClass.id), // Add ValueKey
image: modelClass.thumbUrl,
title: modelClass.title,
year: modelClass.year,
);
},
),
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Usama Karim |
