Home > Blockchain >  retrieve more than expected products when load more data in flutter
retrieve more than expected products when load more data in flutter

Time:01-19

I have this code:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class Scroool extends StatefulWidget {
  const Scroool({Key? key}) : super(key: key);

  @override
  State<Scroool> createState() => _ScrooolState();
}

class _ScrooolState extends State<Scroool> {
  List posts = [];
  int limit = 20;
  bool isLoadingMore = false;
  ScrollController controller = ScrollController();
  @override
  void initState() {
    fetchPosts();
    controller.addListener(scrolListener);
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey.shade300,
      body: ListView.builder(
        controller: controller,
        padding: EdgeInsets.all(20),
        itemCount: isLoadingMore ? posts.length   1 : posts.length,
        itemBuilder: (context, index) {
         if(index < posts.length) {
           final post = posts[index];
           return Card(
             child: ListTile(
               leading: CircleAvatar(child: Text("${index   1}"),),
               title: Text(post['title'].toString()),
               subtitle: Text(post['description']),
             ),
           );
         } else {
           return Center(child: CircularProgressIndicator(),);
         }
        },
      ),
    );
  }

  fetchPosts() async {
    final url = Uri.parse("https://dummyjson.com/products?limit=$limit");
    final response = await http.get(url);
    if(response.statusCode == 200) {
      final json = jsonDecode(response.body)['products'] as List;
      setState(() {
        posts = posts   json;
        isLoadingMore = false;
      });
    } else {
      print("ERROR");
    }
  }

  scrolListener() async{
    //don' call the api if user scroll whil calling the api not finished yet
    if(isLoadingMore) return;
   if(controller.position.pixels ==
   controller.position.maxScrollExtent) {
     setState(() {
       isLoadingMore = true;
     });
     limit =5;
      await fetchPosts();
     setState(() {
       isLoadingMore = false;
     });
   } else {
     print("not called");
   }
  }

}

The problem is when I access the end of the scrolling, add more products, but not only 5 like I have said in the code above, but more? why? and how to fix it?

CodePudding user response:

https://dummyjson.com/products?limit=$limit retrieves limit elements each time you call it. You increase that limit by 5 every time you hit the bottom. Then you do posts = posts json Ie, you are adding those 25 elements you receive from the api to the 20 already existing (giving you 45 elements). Next time you are adding 30 new elements to the 45 already existing and so on and so forth.

Either

  1. completely replace your posts with the retrieved data
  2. only append the last 5 elements from your new list to the existing posts
  3. correctly use the limit and skip parameters docs

I'd suggest to go with the third option. To achieve this there are several options. For instance creating a separate limit and skip variable.

class _ScrooolState extends State<Scroool> {

  int limit = 20;
  int skip = 0;

  fetchPosts() async {
    final url = Uri.parse("https://dummyjson.com/products?limit=$limit&skip=$skip");
    ...
  }

  scrolListener() async{
   if(isLoadingMore) return;
   if(controller.position.pixels == controller.position.maxScrollExtent) {
     setState(() {
      isLoadingMore = true;
     });
     //if the limit is still the initial 20 it will set the skip to 20
     //later it will increase the skip by 5
     skip  = limit;
     //for all subsequent requests set the limit to 5 to only retrieve
     //5 more elements
     limit = 5;
     await fetchPosts();
     ...
  }

}

That you are talking about posts but actually are retrieving products suggests, in your real code, you are using a different API. Of course chosing an option also depends on the capabilities of the API you actually plan to use. But I can only answer you based on what I see in your question. Thus, if your API supports pagination via skip and limit (or similar) use that. Otherwise, use one of the other options I mentioned.

  • Related