flutter - FutureBuilder автоматически перестраивает каждый раз при нажатии кнопки на экране
Я пытаюсь использовать FutureBuilder во Flutter, чтобы дождаться завершения моего initState, а затем создать пользовательский интерфейс для приложения. Но когда приложение запущено, экран перестраивается каждый раз, когда я нажимаю другую кнопку (кнопка делает совершенно разные вещи).
Future loadUser() async {
String jsonString = await storage.read(key: "jwt");
final jsonResponse = json.decode(jsonString);
loggedUser = new LoggedUser.fromJson(jsonResponse);
print(loggedUser.token);
getProfile();
getJourneyByUserId()
.then((receivedList){
addRanges(receivedList);});
}
Future<List<Journey>>getJourneyByUserId() async {
var res = await http.get(
Uri.parse("$baseUrl/journeys/userid=${loggedUser.user.userId}"),
headers: {
'Content_Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ${loggedUser.token}',
},
);
if (res.statusCode == 200) {
print("Get journeys successfully");
}
var data = jsonDecode(res.body);
List idList = [];
for (var i in data) {
idList.add(i["journeyId"]);
}
for (var i in idList) {
var res = await http.get(
Uri.parse("$baseUrl/journeys/$i"),
);
var data = jsonDecode(res.body);
Journey userJourney = new Journey.fromJson(data);
setState(() {
journeyList.add(userJourney);
});
}
print("Journey ${journeyList.length}");
return journeyList;
}
addRanges(journeyList){
setState(() {
rangeList=[];
});
if (journeyList.isNotEmpty) {
for (var i in journeyList) {
DateTime startDate =
DateTime(i.startDate.year, i.startDate.month, i.startDate.day);
DateTime endDate =
DateTime(i.endDate.year, i.endDate.month, i.endDate.day);
setState(() {
rangeList.add(PickerDateRange(startDate, endDate));
});
}
}
print("Range ${rangeList.length}");
return rangeList;
}
returnRange() {
List<PickerDateRange> list = [];
for(int i =0; i<rangeList.length;i++){
list.add(rangeList[i]);
}
return list;
}
Future functionForBuilder() async {
return await returnRange();
}
//initState function
@override
void initState() {
super.initState();
loadUser();
functionForBuilder();
}
//build the UI
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("$_name's Profile",style: TextStyle(color: kColorPalette4),),
centerTitle: true,
),
body: Container(
child: FutureBuilder(
future: functionForBuilder(),
builder: (BuildContext context,AsyncSnapshot snapshot){
//here I set the condition for each case of snapshot
}
Я читал некоторые документы, в которых говорится, что я должен назначить functionForBuilder () переменной Future, когда initState, а затем использовать ее в будущем дочернем элементе FutureBuilder. Пример:
Future _future;
//initState function
@override
void initState() {
super.initState();
loadUser();
_future=functionForBuilder();
}
// then with the FutureBuilder
future: _future
Таким образом, экран больше не перестраивается, но моя функция returnRange(), похоже, не работает как моя expextation(я вызвал returnRange() один раз в функции build ()).
Заранее благодарим за ответ!
3 ответа
Код:
вызовите свое будущее в методе initstate, а не в сборке, как показано в примере.
class MyPage extends StatefulWidget { @override State<MyPage> createState() => _MyPageState(); } class _MyPageState extends State<MyPage> { // Declare a variable. late final Future<int> _future; @override void initState() { super.initState(); _future = _calculate(); // Assign your Future to it. } // This is your actual Future. Future<int> _calculate() => Future.delayed(Duration(seconds: 3), () => 42); @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<int>( future: _future, // Use your variable here (not the actual Future) builder: (_, snapshot) { if (snapshot.hasData) return Text('Value = ${snapshot.data!}'); return Text('Loading...'); }, ), ); } }
Всякий раз, когда вы назначаете
_future
опять же, вы должны сделать это внутри
setState
block, иначе виджет не перестроится с новым будущим.
Например:
void updateData() {
setState(() {
_future = functionForBuilder();
});
}
Если вы используете FutureBuilder, он перестраивает элементы снова и снова.
Попробуйте два способа:
- Не используйте `future: functionForBuilder(), прокомментируйте это.
- Удалите FutureBuilder(), просто используйте Container().
И дайте мне знать о любой проблеме?