Home > Net >  How to call Pagination api in listview.builder
How to call Pagination api in listview.builder

Time:10-12

The company I work with has taken over the backend part and I am providing the information flow with APIs.

While fetch data in the system they wrote, I can only get 20 data and I need to renew this system for the 21st.

But this listview.builder is not working like this or i couldnt handle it.

How should I approuch this issue?

CodePudding user response:

You can listen to the scroll controller and when the listview reaches the bottom try calling pagination and adding values to the list view here is an example of the same.

class MyHome extends StatefulWidget {
  @override
  _MyHomeState createState() => _MyHomeState();
}

class _MyHomeState extends State<MyHome> {
  ScrollController controller;
  List<String> items = List.generate(100, (index) => 'Hello $index');

  @override
  void initState() {
    super.initState();
    controller = ScrollController()..addListener(_scrollListener);
  }

  @override
  void dispose() {
    controller.removeListener(_scrollListener);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Scrollbar(
        child: ListView.builder(
          controller: controller,
          itemBuilder: (context, index) {
            return Text(items[index]);
          },
          itemCount: items.length,
        ),
      ),
    );
  }

  void _scrollListener() {
    print(controller.position.extentAfter);
    if (controller.position.extentAfter < 500) {
      setState(() {
        items.addAll(List.generate(42, (index) => 'Inserted $index'));
      });
    }
  }
}

CodePudding user response:

  1. In the UI part, create a scroll controller to check if we've scrolled to the end. Then the API is called again to get the list of fetch new items with incremented page number.

    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      ScrollController _scrollController = new ScrollController();
      int _page = 1;
      bool isLoading = false;
    
      @override
      void initState() {
        super.initState();
    
        var items = Provider.of<DataProvider>(context, listen: false);
    
        items.fetchAllItems(_page);
    
        _scrollController.addListener(() {
          if (_scrollController.position.pixels ==
              _scrollController.position.maxScrollExtent) {
            items.setLoadingState(LoadMoreStatus.LOADING);
            items.fetchAllUsers(  _page);
          }
        });
      }
    
  2. For the listview, pass the scroll controller value to controller property.

           ListView.separated(
              itemCount: dataProvider.allUsers.length,
              controller: _scrollController,
              shrinkWrap: true,
              physics: const AlwaysScrollableScrollPhysics(),
              itemBuilder: (context, index) {
                // Item builder logic here
              },
              separatorBuilder: (context, index) {
                return Divider();
              },
            ); 
    
  3. Here provider has been used to handle the logic of the pagination.

    enum LoadMoreStatus { LOADING, STABLE }
    
    class ItemProvider with ChangeNotifier {
    
      int totalPages = 0;
      int pageSize = 10;
    
      List<Item> get allUsers => _dataFetcher.data;
      double get totalRecords => _dataFetcher.totalRecords.toDouble();
    
      LoadMoreStatus _loadMoreStatus = LoadMoreStatus.STABLE;
      getLoadMoreStatus() => _loadMoreStatus;
    
      fetchAllUsers(pageNumber) async {
        if ((totalPages == 0) || pageNumber <= totalPages) {   
          ItemModel itemModel =
              await APIService().getData(pageNumber);
          if (_dataFetcher.data == null) {
            totalPages =  ((itemModel.totalRecords - 1) / pageSize).ceil();        
            _dataFetcher = itemModel;
          } else {        
            _dataFetcher.data.addAll(itemModel.data);
            _dataFetcher = _dataFetcher;
    
            // One load more is done will make it status as stable.
            setLoadingState(LoadMoreStatus.STABLE);        
          }      
    
          notifyListeners();
        }
    
        if(pageNumber > totalPages){
          // One load more is done will make it status as stable.
          setLoadingState(LoadMoreStatus.STABLE);      
          notifyListeners();
        }    
      }
    
      setLoadingState(LoadMoreStatus loadMoreStatus) {
        _loadMoreStatus = loadMoreStatus;
        notifyListeners();
      }
    }
    
  4. In the API service class, call the API with the new page number.

    class APIService {
      Future<DataModel> getData(pageNumber) async {
        String url =
            "/GetRadios?pageSize=15&pageNumber=$pageNumber";
    
        print("URL : $url");
        final response = await http.get(Config.apiURL   url);
        if (response.statusCode == 200) {
          return DataModel.fromJson(
            json.decode(response.body),
          );
        } else {
          throw Exception('Failed to load data!');
        }
      }
    }

CodePudding user response:

I would recommend an article that explains the basics of pagination & it will resolve your concern. It is not my article, but I like the simplicity of that article.

Here's the link: https://www.kindacode.com/article/flutter-listview-pagination-load-more/

That article has an example of pagination on a list view widget with page number and page limit API params, lazy loader, and at last, a "you have fetched all of the content" message.

  • Related