我正在尝试用新数据替换ListView,但是这样做并不符合预期。重点是
ListView.builder(
itemBuilder: (context, i) {
return Order(_orders[i]);
}
和
_getOrders() async {
String authToken = await Auth.getAuthToken();
http.Response response = await http.get(
API_URL + '?date=' + _formatDate(_activePeriod),
headers: {'x-auth': authToken});
var parsedJson = json.decode(response.body);
setState(() {
if (parsedJson.runtimeType.toString() != 'List<dynamic>') {
_orders = [];
} else {
_orders = parsedJson;
}
});
}
当应用启动时,第一个渲染是正确的,但是当我按Prev / Next按钮调用_changeMonth
方法时,该方法又调用_getOrders
,它在之后不会重新加载ListView我覆盖了_orders
变量。
如果数组中的项目比以前的项目多,那么我会在末尾看到新添加的项目,但之前的(第一次渲染)项目仍保留在屏幕上。
我可以正确看到新数据,但是在API调用后不能覆盖_orders
变量,因此不会在ListView中呈现新数据。除了使用setState()
之外,我还需要做其他事情吗?
主文件的完整代码。 Order
类是在其他文件中定义的,但我认为这里不是必需的。
class Home extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return HomeState();
}
}
class HomeState extends State {
final DateTime _thisMonth = DateTime.now();
DateTime _activePeriod = DateTime.now();
final String app = 'Orders';
List<dynamic> _orders = [];
bool isLoggedIn = false;
@override
initState() {
super.initState();
Auth.init().then((loggedIn) {
if (loggedIn) {
setState(() {
isLoggedIn = true;
});
_getOrders();
}
});
}
HomeState() {}
@override
build(BuildContext context) {
return MaterialApp(
title: app,
home: Scaffold(
appBar: new AppBar(
title: Text(app),
),
body: isLoggedIn
? ListView.builder(
itemBuilder: (context, i) {
return Order(_orders[i]);
},
itemCount: _orders.length,
)
: Auth.showLoginForm(),
persistentFooterButtons: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
FlatButton(
child: Text('Prev'),
onPressed: () {
_changeMonth(-1);
},
),
FlatButton(
child: Text('Next'),
onPressed: _activePeriod.month == _thisMonth.month
? null
: () {
_changeMonth(1);
},
),
],
)
],
),
);
}
_changeMonth(int increment) async {
setState(() {
_activePeriod =
DateTime(_activePeriod.year, _activePeriod.month + increment, 1);
_getOrders();
});
}
_formatDate(DateTime date) {
return '${date.year}/${date.month}/${date.day}';
}
_getOrders() async {
String authToken = await Auth.getAuthToken();
http.Response response = await http.get(
API_URL + '?date=' + _formatDate(_activePeriod),
headers: {'x-auth': authToken});
var parsedJson = json.decode(response.body);
//print(parsedJson);// new data appears fine
setState(() {
if (parsedJson.runtimeType.toString() != 'List<dynamic>') {
_orders = [];
} else {
_orders = parsedJson;
}
});
}
}
答案 0 :(得分:1)
尝试为Dictionary<string, Func<double, Func<double, double>>> functions = new Dictionary<string, Func<double, Func<double, double>>>
{
{"+", a => b => a + b },
{"-", a => b => a - b },
{"*", a => b => a * b },
{"/", a => b => a / b },
{"^", a => b => Math.Pow(a, b) }
};
functions.Add("Square", a => b => functions["^"](a)(2));
functions.Add("Sqrt", a => b => functions["^"](a)(0.5));
添加密钥
Dictionary<string, Func<double, Func<double, double>>> functions = new Dictionary<string, Func<double, Func<double, double>>>()
{
{"+", a => b => a + b },
{"-", a => b => a - b },
{"*", a => b => a * b },
{"/", a => b => a / b },
{"^", a => b => Math.Pow(a, b) },
{"Square", a => b => functions["^"](a)(2) },
{"Sqrt", a => b => functions["^"](a)(0.5) }
};
您可以使用键来控制框架匹配的小部件 窗口小部件重建时与其他窗口小部件一起使用。默认情况下,框架 根据其匹配当前和先前版本中的小部件 runtimeType及其出现的顺序。使用键, 框架要求两个小部件具有相同的键,以及 相同的runtimeType。