延迟加载json列表视图抖动

时间:2020-05-23 07:05:40

标签: listview flutter dart

我正在尝试为从api中获取的list实现延迟加载。我为ListView实现了一个侦听器,以检查它何时到达底部。我在这里遇到的问题是:

1)如何为列表设置加载项的初始数量?

2)如何在调用loadMore()方法时自动将项目添加到列表中?

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");
  }
}

1 个答案:

答案 0 :(得分:1)

您需要检查,调用分页功能需要显示多少个项目,它可能是10、20、30作为您的要求。在下面的示例中,我假设当时有20个项目,因此在API响应中,您需要检查是否获得了20个项目,或者是否像下面这样。

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;
  }

从上面的代码中,我们知道列表中是否有 20 个项目,或者没有isLoading布尔值。

下一步,我们需要检测listview;底部滚动表示当列表位于底部时,我们的加载更多功能应该起作用。

为此ScrollController进行ListView底部的滚动检测。当我创建了ScrollController列表器并将其添加到Listview的contoller中以检测滚动时。我已经创建了它的演示,请检查一次。第一次加载20个项目,然后我们将调用api加载更多项目。

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();
  }


}

_scrollListener 内,您需要调用API以从分页中获取更多项目