I'm fetching the api data by using http
package and flutter-bloc
package. I successfully implemented the pagination means when i scroll down at bottom fetch the api by incrementing the page no 1. Now the problem is when i scroll down it returns repeated/ duplicate items on scroll down. Now what i did i debug the http response on scroll down it gives correct data then i checked on models, it also gives correct data. Then when i check on Item.builder
it unusually loop/ goback means at starting point when don't scroll the index of an item returns 0 to 3 that is ok. Now when i scroll down the item index should go from 4 to 7 but instead it again goes back from index 0,1 .. index 7. This is what i checked on debugging, Below is the code that on which line i'm doing wrong.
RecommendedForYouPage.dart
class RecommendedForYouPage extends StatefulWidget {
const RecommendedForYouPage({Key? key}) : super(key: key);
@override
_RecommendedForYouPageState createState() => _RecommendedForYouPageState();
}
class _RecommendedForYouPageState extends State<RecommendedForYouPage> {
late RecommendedViewAllBloc recommendedViewAllBloc;
late final ScrollController scrollController = ScrollController();
final List<RecommendedForYouData> recommended = [];
@override
void initState() {
super.initState();
recommendedViewAllBloc = BlocProvider.of<RecommendedViewAllBloc>(context);
recommendedViewAllBloc.add(LoadRestaurantRecommendedViewAllEvent());
}
@override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
return Scaffold(
body: Container(
transform: Matrix4.translationValues(0, -1, 0),
color: TuxedoColor.redColor,
child: Padding(
padding: const EdgeInsets.only(top: 1.0),
child: Container(
decoration: BoxDecoration(
color: TuxedoColor.bodyColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
)),
child: Container(
child: Padding(
padding:
const EdgeInsets.only(top: 20.0, left: 20.0, right: 20.0),
child: Container(
height: height,
child: BlocBuilder<RecommendedViewAllBloc,
RecommendedViewAllState>(
builder: (context, state) {
if (state is RecommendedViewAllStateInitial ||
state is RecommendedViewAllStateLoading &&
recommended.isEmpty) {
return Center(child: CircularProgressIndicator());
} else if (state is RecommendedViewAllStateSuccess) {
recommended.addAll(state.data);
BlocProvider.of<RecommendedViewAllBloc>(context)
.isFetching = false;
} else if (state is RecommendedViewAllStateFailure &&
recommended.isEmpty) {
return Center(child: Text(state.message));
}
return ListView.builder(
controller: scrollController
..addListener(() {
if (scrollController.position.atEdge &&
!BlocProvider.of<RecommendedViewAllBloc>(
context)
.isFetching) {
if (scrollController.position.pixels != 0) {
BlocProvider.of<RecommendedViewAllBloc>(
context)
..isFetching = true
..add(
LoadRestaurantRecommendedViewAllEvent());
}
}
}),
itemBuilder: (context, index) => recommendedListItem(
recommended[index], // On this line giving duplicate items
),
itemCount: recommended.length,
shrinkWrap: true,
primary: false,
scrollDirection: Axis.vertical,
);
},
),
),
),
),
),
),
));
}
recommendedListItem(RecommendedForYouData recommended) {
return Container(
height:200.0,
width:200.0,
child:Text(recommended.branchesLocales![0]!.name!,)
)
}
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
}
RecommendedViewAllBloc
class RecommendedViewAllBloc
extends Bloc<RecommendedViewAllEvent, RecommendedViewAllState> {
RecommendedForYouDataService dataService;
int page = 0;
bool isFetching = false;
RecommendedViewAllBloc(this.dataService)
: super(RecommendedViewAllStateInitial());
@override
Stream<RecommendedViewAllState> mapEventToState(
RecommendedViewAllEvent event,
) async* {
yield RecommendedViewAllStateLoading();
try {
List<RecommendedForYouData> recommended =
await dataService.makeRequestRecommendedForYouViewAll(page)
as List<RecommendedForYouData>;
yield RecommendedViewAllStateSuccess(recommended);
page++;
} catch (e) {
yield RecommendedViewAllStateFailure(e.toString());
}
}
}
RecommendedViewAllEvent
abstract class RecommendedViewAllEvent {}
class LoadRestaurantRecommendedViewAllEvent extends RecommendedViewAllEvent {}
RecommendedViewAllState
abstract class RecommendedViewAllState {}
class RecommendedViewAllStateInitial extends RecommendedViewAllState {}
class RecommendedViewAllStateLoading extends RecommendedViewAllState {}
class RecommendedViewAllStateSuccess extends RecommendedViewAllState {
final List<RecommendedForYouData> data;
RecommendedViewAllStateSuccess(this.data);
}
class RecommendedViewAllStateFailure extends RecommendedViewAllState {
final String message;
RecommendedViewAllStateFailure(this.message);
}
DataService
class RecommendedForYouDataService {
Future<List<RecommendedForYouData>?> makeRequestRecommendedForYouViewAll(
int offset) async {
Location location = new Location();
var latitude = "";
var longitude = "";
LocationData _locationData;
_locationData = await location.getLocation();
latitude = _locationData.latitude.toString();
longitude = _locationData.longitude.toString();
var response = await http.get(Uri.parse(
'$baseURL/restaurant_branches?latitude=$latitude&longitude=$longitude&offset=$offset&limit=4'));
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
List<RecommendedForYouData>? recommendedRestaurant =
RecommendedForYou.fromJson(data).data as List<RecommendedForYouData>;
return recommendedRestaurant;
} else {
throw Exception();
}
}
}
}