如何实现对streambuilder的pull_to_refresh [英] How to implement pull_to_refresh to streambuilder

查看:63
本文介绍了如何实现对streambuilder的pull_to_refresh的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施 pull_to_refresh 。我有两个我将要使用的无状态小部件。首先是 _ProductCategoryDe​​tailPageState 这是代码

i'm trying to implement pull_to_refresh . I have two stateless widget that i will use . First is _ProductCategoryDetailPageState here is the code

  @override
  Widget build(BuildContext context) {
    return Material(
        child: Scaffold(
        appBar: AppBar(
          title: Text(widget.categoryName),
        ),
        body: Container(
          height: MediaQuery.of(context).size.height,
          child: Column(
            children: <Widget>[
              Divider(
                height: 20.0,
              ),
              Flexible(
                  child:StreamBuilder<List<Products>>(
                stream: _productController.stream,
                builder: (context, snapshot) {
                    if (snapshot.hasError) {
                      return errMess(context, "Failed to fetch data");
                    } else {
                      if (snapshot.hasData) {
                        if (snapshot.data.length > 0) {
                          return ProductList(category: snapshot.data);
                        } else {
                          return errMess(context,
                              "There is no available product in this category");
                        }
                      } else {
                        return errMess(context,
                            "There is no available product in this category");
                      }
                    }
                },
              )),
              Divider(
                height: 25.0,
              ),
            ],
          ),
        )));
  }

  loadProduct(String categoryId, int limit, int offset) async {
    List<Products> products = await fetchProducts(http.Client(), categoryId, limit, offset);
    _productController.sink.add(products);
  }
  static List<Products> parseProducts(String responseBody) {
    final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
    return parsed.map<Products>((json) => Products.fromJson(json)).toList();
  }

  Future<List<Products>> fetchProducts(http.Client client, String categoryId, int limit, int offset) async {
    final response = await http.post(Configuration.url +
        "api/getProducts/" +
        categoryId +
        "/" +
        limit.toString() +
        "/" +
        offset.toString());
    if (response.statusCode < 200 || response.statusCode > 300) {
      throw new Exception('Failed to fetch data');
    } else {
      return compute(parseProducts, response.body);
    }
  }

这是我的第二个无状态小组件

and here is my second stateless widget

class _ProductListState extends State<ProductList> {
  int limit = 0;
  int offset = 4;

  RefreshController _refreshController2 =
      RefreshController(initialRefresh: false);

  @override
  Widget build(BuildContext context) {
    return SmartRefresher(
      child: new GridView.builder(
        itemCount: widget.category.length,
        gridDelegate:
            new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
        itemBuilder: (BuildContext context, int index) {
          return new GestureDetector(
            onTap: () {
              print("Product detail");
            },
            child: Card(
              semanticContainer: true,
              clipBehavior: Clip.antiAliasWithSaveLayer,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Expanded(
                    child: Image.network(
                      Configuration.url +
                          "assets/app_assets/" +
                          widget.category[index].productImage,
                      width: 250,
                      height: 250,
                      filterQuality: FilterQuality.low,
                    ),
                  ),
                  SizedBox(
                    height: 25,
                  ),
                  Text(
                    widget.category[index].productName,
                    style: TextStyle(fontSize: 15.0),
                  ),
                  SizedBox(
                    height: 25,
                  ),
                ],
              ),
            ),
          );
        },
      ),
      controller: _refreshController2,
      enablePullUp: true,
      header: MaterialClassicHeader(),
      onRefresh: () {
        _onRefresh(_refreshController2, widget.category,
            widget.category[0].categoryId);
      },
      onLoading: () {
        _onLoading(_refreshController2, widget.category,
            widget.category[0].categoryId);
      },
    );
  }

  void _onLoading(RefreshController controller, List<Products> data,String categoryId) async {
    await Future.delayed(Duration(milliseconds: 2000));
    setState(() {
      limit = limit + offset;
      offset = 6;
    });

   _ProductCategoryDetailPageState().loadProduct(categoryId, limit, offset);

    controller.loadComplete();
  }

  void _onRefresh(RefreshController controller, List<Products> data,
      String categoryId) async {
    await Future.delayed(Duration(milliseconds: 1000));
    controller.refreshCompleted();
  }
}

当我拉网格时没有错误,但是数据不变。在我检查了这部分之后

when i pull the grid there is no error , but the data is not change. After i check on this part

    Flexible(
                      child:StreamBuilder<List<Products>>(
                    stream: _productController.stream,
                    builder: (context, snapshot) {
print("run")
                        if (snapshot.hasError) {
                          return errMess(context, "Failed to fetch data");
                        } else {
                          if (snapshot.hasData) {
                            if (snapshot.data.length > 0) {
                              return ProductList(category: snapshot.data);
                            } else {
                              return errMess(context,
                                  "There is no available product in this category");
                            }
                          } else {
                            return errMess(context,
                                "There is no available product in this category");
                          }
                        }
                    },
                  )),

您可以看到我添加了 print( run),它仅显示一次。

As you can see i adding print("run") , it just only showing once.

我完整脚本 https://gist.github.com/bobykurniawan11/04f2584c6de97f1d9324bfe3b24f669> b $ b

my full script https://gist.github.com/bobykurniawan11/04f2584c6de97f1d9324bfe3b24f669f

推荐答案

这在您创建State对象的新State实例时将不起作用。

This won't work as you are creating a new State instance of the State object. You should connect both widgets with a callback for example.

_ProductCategoryDetailPageState().loadProduct(categoryId, limit, offset);

就像这样:

// Custom callback function
typedef void OnLoadProductsFunction(String categoryId, int limit, int offset); 

class ProductList extends StatefulWidget {
    OnLoadProductsFunction onLoad;

    ProductList({
        this.category,
        this.onLoad,
    })
}

...

 void _onLoading(RefreshController controller, List<Products> data,String categoryId) async {
    await Future.delayed(Duration(milliseconds: 2000));
    setState(() {
      limit = limit + offset;
      offset = 6;
    });

    widget.onLoad(categoryId, limit, offset);

    controller.loadComplete();
}

...


// In the parent widget
return ProductList(
    category: snapshot.data
    onLoad: (categoryId, limit, offset) {
        loadProduct(categoryId, limit, offset);
    }
);

这样做可以从回调函数中更新流控制器。您还可以选择将 StreamController 实例传递给 ProductList 小部件,并且该子项是添加产品列表的子级到水槽。

Doing it this way the streamcontroller will be updated from the callback function. Other option you have is to pass the StreamController instance to the ProductList widget and is the child who adds the list of products to the sink.

这篇关于如何实现对streambuilder的pull_to_refresh的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆