【问题标题】:Add infinite scroll to GridView.builder to flutter FutureBuilder向 GridView.builder 添加无限滚动以使 FutureBuilder 颤动
【发布时间】:2021-10-06 17:46:15
【问题描述】:

我很难在颤动中无限滚动。 我试图先加载 10 个菜谱,然后在 ScrollController 的帮助下显示新菜谱。 当没有更多的食谱时,我想显示一条消息,表明没有更多的帖子。

这是我项目的代码。

import 'package:flutter/material.dart';
import 'package:test/model/recipe.dart';
import 'package:test/pages/recipe_details.dart';
import 'package:test/widgets/recipe_card.dart';
import 'package:http/http.dart' as http;

class SingleCategory extends StatefulWidget {
  final Recipe recipe;
  final int recipeCourseid;
  final String recipeCourseName;

  SingleCategory({
    this.recipe,
    @required this.recipeCourseid,
    @required this.recipeCourseName,
  });

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

class _SingleCategoryState extends State<SingleCategory> {
  ScrollController _scrollController = ScrollController();
  int pageNumber = 1;

  var myRecipe;

  Future<List<Recipe>> getRecipeList({int pageNumber}) async {
    // pageNum = 1;
    var response = await http.get(
        'https://test.com/wp-json/wp/v2/wprm_recipe?wprm_course=${widget.recipeCourseid}&per_page=10&$pageNumber');
    var body = response.body;
    final recipes = recipeFromJson(body)

    return recipes;
  }

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

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

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.recipeCourseName),
          centerTitle: true,
          elevation: 5,
        ),
        body: Padding(
          padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 12.0),
          child: FutureBuilder(
            future: getRecipeList(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return GridView.builder(
                  controller: _scrollController,
                  itemCount: snapshot.data.length,
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 2,
                    crossAxisSpacing: 12.0,
                    mainAxisSpacing: 12.0,
                  ),
                  itemBuilder: (BuildContext context, int index) {
                    myRecipe = snapshot.data[index].recipe;
                    return InkWell(
                      onTap: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) => RecipeDetails(
                              recipe: snapshot.data[index],
                            ),
                          ),
                        );
                      },
                      child: RecipeCard(myRecipe: myRecipe),
                    );
                  },
                );
              } else if (snapshot.hasError) {
                return Center(
                  child: Text('There was an error, Please try again'),
                );
              } else {
                return Center(
                  child: CircularProgressIndicator(),
                );
              }
            },
          ),
        ),
      ),
    );
  }
}

如果你能指出正确的方向,我会很感激。

【问题讨论】:

    标签: flutter flutter-layout flutter-futurebuilder flutter-listview flutter-gridview


    【解决方案1】:

    在你的类中声明一个新变量

     List<Recipe> recipesList;
    

    并且在 getRecipeList() 方法内部更改如下

    Future<List<Recipe>> getRecipeList({int pageNumber}) async {
        // pageNum = 1;
    If(page number ==1)
      recipesList.clear;
    
        var response = await http.get(
            'https://test.com/wp-json/wp/v2/wprm_recipe?wprm_course=${widget.recipeCourseid}&per_page=10&$pageNumber');
        var body = response.body;
        final recipes = recipeFromJson(body)
        recipesList.addAll(recipes);
        return recipesList;
      }
    

    并在scrollListener 中尝试传递pageNumber。由于您在 getRecipesList 方法内部和外部都为 pageNumber 声明了相同的名称。

    _scrollController.addListener(() {
          if (_scrollController.position.pixels ==
              _scrollController.position.maxScrollExtent) {
            pageNumber++;
            print(pageNumber);
            getRecipeList(pageNumber:pageNumber).then((){
                setState((){});
            });
          }
        });
    

    【讨论】:

    • 感谢您的这部分代码进行了一些编辑,但第一个答案需要较少的修改 _scrollController.addListener( () { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { pageNumber++; setState(() { getRecipeList(); }); } }, );
    【解决方案2】:

    一切看起来都不错,但你必须做些小改动。

    您的代码:

    _scrollController.addListener(() {
          if (_scrollController.position.pixels ==
              _scrollController.position.maxScrollExtent) {
            pageNumber++;
            print(pageNumber);
            getRecipeList();
          }
        });
    

    应该是:

    _scrollController.addListener(() {
          if (_scrollController.position.pixels ==
              _scrollController.position.maxScrollExtent) {
            pageNumber++;
            setState(() {}); // if add this, Reload your futurebuilder and load more data
     //        getRecipeList(); // It's not necessary because, FutureBuilder call automatically getRecipeList when you call setState 
          }
        });
    

    【讨论】:

    • 其实你是对的。我发现了另一个错误并解决了这个问题。谢谢
    【解决方案3】:

    尝试在你的 GridView 中添加

    physics: const AlwaysScrollableScrollPhysics(),

    【讨论】:

    • 感谢您抽出宝贵时间,但我的问题不在于滚动,我认为问题在于我无法向已经显示的帖子添加新帖子
    猜你喜欢
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 2014-03-29
    • 2017-01-06
    相关资源
    最近更新 更多