在列表视图生成器中从服务器颤动无限滚动数据

flutter infinite scrolling data from server in listview builder

我正在使用 graphql_flutter 从服务器加载数据,我应该为我的服务器更新页面更新 moreId 并加载更多数据,我需要为此使用 infinite。

我该怎么做?

class MoreEpd extends StatefulWidget {
      final String moreId;
      const MoreEpd({Key? key, required this.moreId}) : super(key: key);
    
      @override
      _MoreEpdState createState() => _MoreEpdState();
    }
    
    class _MoreEpdState extends State<MoreEpd> {
      double pageWidth = 0;
      double pageHeigh = 0;
      int pageNum = 0;
    
      final String leftArrow = 'assets/icons/left-arrow.svg';
      String getSearchResult = """
     query homeview($moreId: ID!, $page: Int! ){
        homeview(HM_ID: $moreId, page: $page){
        HM_ID
        HM_Type_ID
        HM_Type_Name
        HM_NAME
        Priority
        Details{
          HM_Det_ID
          HM_ID
          Ep_ID
          Pod_ID
          Link
          Image
          title
          Pod_title
          
        }
      }
    }
    """;
    
      @override
      Widget build(BuildContext context) {
        pageWidth = MediaQuery.of(context).size.width;
        pageHeigh = MediaQuery.of(context).size.height;
        return Container(
          child: Query(
            options: QueryOptions(
              document: gql(getSearchResult),
              variables: {'moreId': widget.moreId, 'page': pageNum},
            ),
            builder: (
              QueryResult result, {
              Refetch? refetch,
              FetchMore? fetchMore,
            }) {
              return handleResult(result);
            },
          ),
        );
      }
     Widget handleResult(QueryResult result) {
        var data = result.data!['homeview']['Details'] ?? [];
    
        return Container(
            child: ListView.builder(
                padding: EdgeInsets.only(top: 15),
                shrinkWrap: true,
                itemCount: data.length ,
                itemBuilder: (context, index) {
                  return InkWell(
                    onTap: () {},
                    child: Padding(
                      padding: EdgeInsets.only(
                          top: pageWidth * 0.0,
                          right: pageWidth * 0.08,
                          left: pageWidth * 0.08,
                          bottom: pageWidth * 0.0),
                      child: Container(
                        child: Stack(
                          children: [
                            Column(
                              children: [
                                Padding(
                                  padding:
                                      EdgeInsets.only(bottom: pageWidth * 0.060),
                                  child: Row(
                                    children: [
                                      Padding(
                                        padding:
                                            EdgeInsets.only(left: pageWidth * 0.01),
                                        child: Container(
                                          // alignment: Alignment.centerRight,
                                          width: pageWidth * 0.128,
                                          height: pageWidth * 0.128,
                                          decoration: BoxDecoration(
                                              image: DecorationImage(
                                                  fit: BoxFit.cover,
                                                  image: CachedNetworkImageProvider(
                                                    data[index]['Image'],
                                                  )),
                                              borderRadius: BorderRadius.all(
                                                  Radius.circular(15)),
                                              // color: Colors.redAccent,
                                              border: Border.all(
                                                color: MyColors.lightGrey,
                                                width: 1,
                                              )),
                                        ),
                                      ),
                                      Expanded(
                                        child: Row(
                                          children: [
                                            Column(
                                              crossAxisAlignment:
                                                  CrossAxisAlignment.start,
                                              children: [
                                                Container(
                                                  width: pageWidth * 0.5,
                                                  alignment: Alignment.centerRight,
                                                  child: Text(
                                                    data[index]['title'],
                                                    textAlign: TextAlign.right,
                                                    overflow: TextOverflow.ellipsis,
                                                    maxLines: 1,
                                                    // softWrap: true,
                                                    style: TextStyle(
                                                      // fontWeight: FontWeight.bold,
                                                      fontSize: 14,
                                                    ),
                                                  ),
                                                ),
                                              ],
                                            ),
                                          ],
                                        ),
                                      )
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ),
                  );
                }));
      }
    }

第一个错误是由于未处理 Query 的状态而发生的。为了在 builder:

上做到这一点

delearing data on state level var data = [];

     builder: (
                QueryResult result, {
                Refetch? refetch,
                FetchMore? fetchMore,
              }) {
                if (result.hasException) {
                  return Text(result.exception.toString());
                }
                if (result.isLoading) {
                  return Column(
                    children: [
                      Expanded(
                          child: handleResult(data)), // show data while loading
                      const Center(
                        child: CircularProgressIndicator(),
                      ),
                    ],
                  );
                }
                data.addAll(result.data!['homeview']['Details'] ?? []);
                return handleResult(data);
              },

我们现在只需要增加 pageNum 以获得更多数据。我正在使用加载更多按钮,最好是通过增加 itemLength+=1.

创建加载按钮列表末尾

更新 使用 ScrollController.

// on state class
  final ScrollController controller = ScrollController();
  bool isLoading = false;

滚动加载数据

  @override
  void initState() {
    super.initState();
    controller.addListener(() {
      /// load date at when scroll reached -100
      if (controller.position.pixels >
          controller.position.maxScrollExtent - 100) {
        print("Scroll on loading");
        if (!isLoading) {
          print("fetching");
          setState(() {
            pageNum++;
            isLoading = true;
          });
        }
      }
    });
  }

完整代码段on Gist

关于位置问题,可以查看this