1

I want to implement pagination when calling APIs(without any packages) with my FutureBuilder, that calls 2 APIs at the same time since one depends on the other and I'm not sure how to do that. Here is the code below:

The ListView from FutureBuilder:

final ScrollController _scrollController = ScrollController();


@override
  void initState() {
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {}
    });
    super.initState();
  }

FutureBuilder(
        future: Future.wait(
          [
            RepositoryFromAPItoDB().getAllMovies(),
            RepositoryFromAPItoDB().getAllGenres()
          ],
        ),
        builder:
            (BuildContext context, AsyncSnapshot<List<dynamic>?> snapshot) {
          if (!snapshot.hasData) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          } else {
            return ListView.builder(
              controller: _scrollController,
              itemCount: snapshot.data?[0].length,
              itemBuilder: (BuildContext context, int index) {
                return MoviesListTile();
              },
            );
          }
        },
      ),

API calls for both Lists:

Future<List<Movies?>> getAllMovies() async {
    Response response = await Dio().get(Constants().moviesURL);

    return (response.data['results'] as List).map((movies) {
      return Movies.fromJson(movies);
    }).toList();
  }

  Future<List<Genres?>> getAllGenres() async {
    Response response = await Dio().get(Constants().genresURL));

    return (response.data['genres'] as List).map((genres) {
      return Genres.fromJson(genres);
    }).toList();
  }

Now that I have call the APIs, my list is populated and everything is working fine, except I can't implement any type of pagination.. And how do I display some sort of CircularProgressIndicator() or anything like that while I scroll the bottom of the list and when it loads again? Thanks in advance for your help!

GrandMagus
  • 600
  • 3
  • 12
  • 37

1 Answers1

0

import 'package:flutter/material.dart';
import 'package:pageview_demo/main.dart';
import 'package:pageview_demo/usersModel.dart';

import 'DataNum.dart';

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

  @override
  _SchoolState createState() => _SchoolState();
}

class _SchoolState extends State<School> with AutomaticKeepAliveClientMixin {
  ScrollController _scrollController = ScrollController(keepScrollOffset: true);
  int pageNo = 1;
  bool isLoading = false;
  List<UsersModel> _usersModel = [];
  List<Datum> data = [];

  @override
  void initState() {
    _scrollController.addListener(() {
      final pos = _scrollController.position;
      final triggerFetchMoreSize = 0.9 * pos.maxScrollExtent;
      if (pos.pixels > triggerFetchMoreSize) {
        Future.delayed(const Duration(seconds: 5), () {
          _callApi();
        });
      }
    });
    _callApi();
    super.initState();
  }

  _callApi() async {
    var response = await getHttp();
    isLoading = true;
    _usersModel.clear();
    setState(() {
      if (data.isEmpty) {
        _usersModel.add(response);
        data.addAll(_usersModel[0].data);
        isLoading = false;
      } else {
        _usersModel.add(response);
        data.insertAll(data.length, _usersModel[0].data);
        isLoading = false;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: () async {
        pageNo = 1;
        isLoading = true;
        _usersModel.clear();
        data.clear();
        _callApi();
      },
      child: ListView.builder(
        padding: EdgeInsets.all(10),
        shrinkWrap: true,
        scrollDirection: Axis.vertical,
        controller: _scrollController,
        physics: const BouncingScrollPhysics(),
        itemCount: isLoading ? 0 : data.length,
        itemBuilder: (context, indx) => indx == data.length - 1
            ? Center(child: LinearProgressIndicator())
            : ListTile(
          onTap: (){},
                leading: Text("${data[indx].id}"),
                title: Text("${data[indx].name}"),
                subtitle: Text("${data[indx].email}"),
              ),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}
MohitJadav86
  • 782
  • 3
  • 11
  • 2
    I think you should add a bit of text to explain what your code does/what solution it proposes to your answer – fravolt Aug 24 '22 at 12:02