1

I am trying to implement a lazy loading for a list that I am fetching from api. I have implemented a listener for my ListView to check when it reaches the bottom. The issue I have here is:

1) How do I set an initial number of loaded items for my list?

2) How do I automatically add items to the list while calling my loadMore() method?

class _HomeServiceState extends State<HomePage>
    with AutomaticKeepAliveClientMixin {
   List<Mentor> filteredData;

  List<Mentor> users = [];
 @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _scrollcontroller.addListener(() {
      if (_scrollcontroller.position.atEdge) {
        if (_scrollcontroller.position.pixels == 0){
      // you are at top position

        } else{
      // you are at bottom position
          loadMore();
        }
    }
    });
  }

  @override
  Widget build(BuildContext context) {
    final mentors = new FutureBuilder(
      future: _future,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
          return  ListView.builder(
              shrinkWrap: true,
              physics: ScrollPhysics(),
              itemCount: filteredData.length + 1,
              itemBuilder: (BuildContext context, int index) {
                if (index == filteredData.length) {
                  return CupertinoActivityIndicator();
                }
                return ListTile(
                  leading: CircleAvatar(
                    maxRadius: 23,
                    backgroundImage: NetworkImage(NetworkUtils.host +
                        AuthUtils.profilePics +
                        filteredData[index].profile_image),
                  ),
                  title: Text(
                      filteredData[index].first_name +
                          " " +
                          filteredData[index].last_name,
                      style: TextStyle(
                        color: Color(0xFF041F36),
                        fontFamily: 'Muli',
                        fontSize: 16.0,
                      )),
                  subtitle: Text(capitalize(filteredData[index].industry),
                      style: TextStyle(
                        color: Color(0xFF25282A),
                        fontFamily: 'MuliLight',
                        fontSize: 12.0,
                      )),
                  trailing: Text(capitalize(filteredData[index].country),
                      style: TextStyle(
                        color: Color(0xFF25282A),
                        fontFamily: 'MuliItalic',
                        fontSize: 12.0,
                      )),
                  onTap: () {
                    Navigator.push(
                        context,
                        SlideFromRightPageRoute(
                            widget: MenteeDetailPage(filteredData[index])));
                  },
                );
              },
            );
        }
      },
    );

  Future<List<Mentor>> _getUsers() async {
    sharedPreferences = await SharedPreferences.getInstance();
    var data = await http.get(
      NetworkUtils.host + AuthUtils.endPointMentors,
      headers: {
        'Authorization': "Bearer " + sharedPreferences.getString("token"),
        'Accept': 'application/json'
      },
    );
    var jsonData = json.decode(data.body);
    for (var u in jsonData["data"]) {
      Mentor user = Mentor(
        u["id"]!=null ? u["id"]: "",
        u["category"]!=null ? u["category"] : "",
        u["email"]!=null ? u["email"]: "",
        u["email_verified_at"] !=null ? u["email_verified_at"]: "",
        u["first_name"] !=null ? u["first_name"]: "",
        u["last_name"] != null ?u["last_name"]: "",
        u["other_name"] !=null ? u["other_name"]: "",
        u["country"] !=null ? u["country"]: "",
        u["industry"] !=null ? u["industry"]: "",
        u["gender"] !=null ? u["gender"]: "",
        u["bio_interest"] !=null ? u["bio_interest"]: "",
        u["phone"] !=null ?u["phone"]: "",
        u["state_of_origin"] !=null ? u["state_of_origin"]: "",
        u["fav_quote"] != null ? u["fav_quote"]: "",
        u["profile_image"] != null ? u["profile_image"] : "",
        u["terms"] !=null ? u["terms"]: "",
        u["check_status"] !=null ? u["check_status"]: "",
        u["current_job"] != null ? u["current_job"]: "",
        u["created_at"] !=null ? u["created_at"]: "",
        u["updated_at"]!=null ? u["updated_at"]: "",
        u["social_id"] !=null ? u["social_id"]: "",
        getFromList(u["employment"], 'company'),
        getFromList(u['employment'], 'position'),
        getFromList(u['education'], 'institution'),
        getFromList(u['education'], 'degree'),);

      users.add(user);
    }
    filteredData = users;
    return filteredData;
  }
  String getFromList(Map<String, dynamic> json, String key) {
    return json != null ? json[key] : "";
  }
  @override
  void dispose() {
    _scrollcontroller.dispose();
    super.dispose();
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;

  loadMore() {
    print("edkwj");
  }
}
5
  • Check the link for the load more functionality stackoverflow.com/a/61708445/3946958 , let me know in case of concern Commented May 23, 2020 at 7:06
  • @RavindraKushwaha how do I set a initial loaded number of items for my type of lists. This line of code: (List<String> items = new List.generate(100, (index) => 'Hello $index');) was not helpful to me Commented May 23, 2020 at 7:32
  • Are you getting the response from API in any format like 20 ,10 OR 30 item at a time, let me know..I will post the answer accordinngly Commented May 23, 2020 at 7:33
  • yes I am, I fetch all items into a list called users seen in my code Commented May 23, 2020 at 7:40
  • please check the below solution and let me know in case of concern Commented May 23, 2020 at 8:01

1 Answer 1

2

You need to make check that , how many item you need to show for calling the pagination functionality , it could be 10,20,30 as your requirement. In my below example i am assuming the 20 items at time, So inside in your API response , you need to make check that you are getting the 20 items or not a time like below.

Future<List<Mentor>> _getUsers() async {
    sharedPreferences = await SharedPreferences.getInstance();
    var data = await http.get(
      NetworkUtils.host + AuthUtils.endPointMentors,
      headers: {
        'Authorization': "Bearer " + sharedPreferences.getString("token"),
        'Accept': 'application/json'
      },
    );
    var jsonData = json.decode(data.body);
    for (var u in jsonData["data"]) {
      Mentor user = Mentor(
        u["id"] != null ? u["id"] : "",
        u["category"] != null ? u["category"] : "",
        u["email"] != null ? u["email"] : "",
        u["email_verified_at"] != null ? u["email_verified_at"] : "",
        u["first_name"] != null ? u["first_name"] : "",
        u["last_name"] != null ? u["last_name"] : "",
        u["other_name"] != null ? u["other_name"] : "",
        u["country"] != null ? u["country"] : "",
        u["industry"] != null ? u["industry"] : "",
        u["gender"] != null ? u["gender"] : "",
        u["bio_interest"] != null ? u["bio_interest"] : "",
        u["phone"] != null ? u["phone"] : "",
        u["state_of_origin"] != null ? u["state_of_origin"] : "",
        u["fav_quote"] != null ? u["fav_quote"] : "",
        u["profile_image"] != null ? u["profile_image"] : "",
        u["terms"] != null ? u["terms"] : "",
        u["check_status"] != null ? u["check_status"] : "",
        u["current_job"] != null ? u["current_job"] : "",
        u["created_at"] != null ? u["created_at"] : "",
        u["updated_at"] != null ? u["updated_at"] : "",
        u["social_id"] != null ? u["social_id"] : "",
        getFromList(u["employment"], 'company'),
        getFromList(u['employment'], 'position'),
        getFromList(u['education'], 'institution'),
        getFromList(u['education'], 'degree'),);

      users.add(user);
    }
    filteredData = users;
    ////HERE ARE MAKING THE CHECK THE LOAD MORE FUNCTIONALITY
    if (users.length == 20) {
      isLoading = true;
    }
    else {
      isLoading = false
    }

    return filteredData;
  }

From above code , we come to know that there is 20 items in the list or not with isLoading boolean.

Next step we need to detect the listview;s bottom scroll means when list come at the bottom then our load more functionality should work.

For it ScrollController for the scrolling detection at the bottom for the ListView . As i have created the ScrollController listner and added to the Listview's contoller for the detection of the scroll. I have created the demo of it , please check it once. At first time it load the 20 items and then afet we will call api to load more items.

class _HomeScreen extends State<HomeScreen> {
  List dataList = new List<int>();
  bool isLoading = false;
  int pageCount = 1;
  ScrollController _scrollController;

  @override
  void initState() {
    super.initState();

    _scrollController = new ScrollController(initialScrollOffset: 5.0)
      ..addListener(_scrollListener);
  }

  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Gridview',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primaryColor: Colors.red,
          accentColor: Color(0xFFFEF9EB),
        ),
        home: Scaffold(
            appBar: new AppBar(),
            body: ListView.builder(
              shrinkWrap: true,
              controller: _scrollController,  //// YOU ARE ADDING THE CONTROLLER HERE TO ADD THE SCROLL LISTENER
              physics: ScrollPhysics(),
              itemCount: filteredData.length + 1,
              itemBuilder: (BuildContext context, int index) {
                if (index == filteredData.length) {
                  return CupertinoActivityIndicator();
                }
                return ListTile(

                );
              },
            )));
  }

  //// ADDING THE SCROLL LISTINER
  _scrollListener() {
    if (_scrollController.offset >=
        _scrollController.position.maxScrollExtent &&
        !_scrollController.position.outOfRange) {
      setState(() {
        print("comes to bottom $isLoading");
        isLoading = true;

        if (isLoading) {
          print("RUNNING LOAD MORE");

          pageCount = pageCount + 1;


          //// CALL YOUR API HERE FOR THE NEXT FUNCTIONALITY
         getUsers();

        }
      });
    }
  }



  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }


}

Inside the _scrollListener you need to call API to get more item from the pagination

Sign up to request clarification or add additional context in comments.

7 Comments

how do I use the page count variable? what does it do?
Pagecout variable refer to the number of load more you require for the list...you just need to give the pagecout to your API which load the from 1 to every increment value until the load data not available on the server
how do I specify load count for my api list? that's the real issue I have
You need to take paramter as request in API , in which you need to pass the pagecout from 0 to pagecout+1 on each load more call until data is not available on the server side
how do I know when data is not available on the server side
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.