我正在尝试实现pull_to_refresh。我有两个我将要使用的无状态小部件。首先是_ProductCategoryDetailPageState
,这里是代码
@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);
}
}
这是我的第二个无状态小组件
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();
}
}
当我拉网格时没有错误,但是数据没有改变。在我检查了这部分之后
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")
,它只显示了一次。
我的完整脚本https://gist.github.com/bobykurniawan11/04f2584c6de97f1d9324bfe3b24f669f
答案 0 :(得分:1)
这在您创建State对象的新State实例时不起作用。例如,您应该使用回调将两个小部件连接起来。
_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。您还需要执行的另一种选择是将StreamController
实例传递到ProductList
小部件,并且是将产品列表添加到接收器的孩子。