![](/img/trans.png)
[英]Flutter stateful widget is not updating while calling from Navigation drawer
[英]How to update stateful widget in Navigation drawer while keeping same class like fragments in Android?
我想更新类的有状态小部件,同时从服务器,导航抽屉中获取数据后返回同一个类。 我遇到的问题是该类仅加载一次数据,如果我导航到导航抽屉的另一项,则保持不变。 因为状态仅创建一次。
这是我的代码:
class CategoryFilter extends StatefulWidget {
int productIndex;
String category_name;
CategoryFilter(this.productIndex, this.category_name)
{
print("CategoryFilter");
print(productIndex);
print(category_name);
new _CategoryFilterState(productIndex, category_name);
}
@override
_CategoryFilterState createState() => new
_CategoryFilterState(productIndex, category_name);
}
class _CategoryFilterState extends State<CategoryFilter> {
int productIndex;
List<ResponseDataProducts> productList;
List data;
String category_name;
_CategoryFilterState(this.productIndex, this.category_name)
{
print("CategoryFilter");
print(productIndex);
print(category_name);
}
@override
void initState(){
super.initState();
Future<String> status = getData(productIndex);
status.then((onValue){
if(onValue.toString() == "Success")
{
Navigator.pop(context);
}
});
// this.getData();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Container(
color: Colors.white30,
child: new ListView.builder(
itemCount: productList == null ? 0 : productList.length,
itemBuilder: (BuildContext context, int index) {
return new Container(
margin: const EdgeInsets.only( bottom: 10.0),
constraints: new BoxConstraints.expand(
height: 200.0
),
alignment: Alignment.bottomLeft,
decoration: new BoxDecoration(
image: new DecorationImage(image:
new NetworkImage
("http://myurl.com/"+productList[index].thumbnail),
fit: BoxFit.cover)
),
child:new Container(
child: new Text(
productList[index].name,
style: new TextStyle(color: Colors.white, fontSize: 30.0),
),
color: Colors.black54,
alignment: new FractionalOffset(0.5, 0.0),
height: 35.0,
// margin: const EdgeInsets.symmetric(vertical: 30.0),
),
);
})
),
) ;
}
void _onLoading()
{
showDialog(context: context,
barrierDismissible: false,
child: progress);
new Future.delayed(new Duration(seconds: 2), (){
// Navigator.pop(context);
});
}
Future<String> getData(int productIndex) async {
productList = new List<ResponseDataProducts>();
_onLoading();
http.Response response = await http.get(
Uri.encodeFull(CommonMethods.base_url + 'product/$productIndex'),
headers: {"Accept": "application/json"});
print(response.body);
setState(() {
var convertDataToJson = JSON.decode(response.body);
data = convertDataToJson["responseData"];
for(int i=0; i<data.length; i++)
{
ResponseDataProducts responseData = new ResponseDataProducts(
data[i]["id"],
data[i]["name"], data[i]["description"],
data[i]["title"], data[i]["thumbnail"]);
productList.add(responseData);
}
//Navigator.pop(context);
});
return "Success";
}
}
这是我从导航抽屉中调用categoryFilter类的方式:
_getDraserItemWidget(int pos)
{
switch(pos)
{
case 0:
return new Home(bar_id);
case 1:
return new CategoryFilter(categoryList[pos-1].id, categoryList[pos-1].name);
case 2:
return new CategoryFilter(categoryList[pos-1].id, categoryList[pos-1].name);
case 3:
return new CategoryFilter(categoryList[pos-1].id, categoryList[pos-1].name);
case 4:
return new OpeningTime();
case 5:
break;
}
}
我建议您使用FutureBuilder
小部件,而不是调用该方法在类的initState
方法内加载数据。 如果从导航抽屉返回一个新的FutureBuilder
,则每次创建一个新的FutureBuilder
都应该调用您的服务,这通常是执行异步请求的更好方法。
这是一个非常简单的示例。 它不能很好地完成抽屉操作(或其他一些事情-只能花很多时间在这样的事情上),但是它应该可以说明这个概念。
请注意,与其“更新小部件”,不如说只是创建一个新的小部件。 由于颤动的执行方式,因此它应该相对来说性能较高,尤其是因为您并非一直在执行此操作,而是仅在用户从导航菜单中选择某个内容时才这样做。
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => new MyAppState();
}
class MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new TextPage(text: "Home!"),
);
}
}
Map<int, int> _nums = Map();
class TextPage extends StatelessWidget {
final String text;
const TextPage({Key key, @required this.text}) : super(key: key);
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new PreferredSize(
child: new Container(),
preferredSize: Size.fromHeight(10.0),
),
body: new Center(
child: new Text(text),
),
drawer: new Builder(
builder: (context) => Material(
child: new SafeArea(
child: Column(
children: <Widget>[
new FlatButton(
onPressed: () {
Navigator.pushReplacement(
context, new MaterialPageRoute(builder: (context) => _getDrawerItemWidget(1)));
},
child: Text("First item"),
),
new FlatButton(
onPressed: () {
Navigator.pushReplacement(
context, new MaterialPageRoute(builder: (context) => _getDrawerItemWidget(2)));
},
child: Text("Second item"),
),
],
),
),
),
),
);
}
_getDrawerItemWidget(int i) {
return new FutureBuilder<String>(
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.data != null) {
return new TextPage(text: snapshot.data);
} else {
return new TextPage(text: "Loading.");
}
},
future: () async {
var num = _nums.putIfAbsent(i, () => 0);
_nums[i] = num + 1;
String toReturn = "You retrieved number $i for the $num time";
return await Future.delayed<String>(Duration(seconds: 1), () => toReturn);
}(),
);
}
}
从理论上讲,您可以在保留GlobalKey引用并使用它们调用子小部件上的方法(如果它与当前选择匹配,以使其进行更新)上做一些不同的操作,但这通常是一个不好的主意-最佳做法鼓励您向下传递数据到小部件树,而不是向下调用函数。 如果必须使用GlobalKeys,通常可以重构以做得更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.