У меня есть экран с информацией о пользователе.
В моем виджете сборки у меня есть это:
Column
(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>
[
Text('User Points', style: TextStyle(color: Colors.blueAccent)),
Text('${this.user.points}', style: TextStyle(color: Colors.black, fontWeight: FontWeight.w700, fontSize: 34.0))
],
),
И у меня есть функция для обновления приборной панели каждый раз, когда пользователь получает к ней доступ.
void updateDashboard() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
var api_key = prefs.getString('api_key');
var userID = prefs.getInt('userID');
var res = await http.post(('http://myApp.com/getDashboardPreferences/'+userID.toString() + '/' + api_key),
headers: {
"Accept": "application/json",
"content-type": "application/json"
});
this.user = User.fromJson(json.decode(res.body));
setState(() {
if (res.statusCode == 200) {
this.user.setPoints(this.user.points);
} else {
print("Something is wrong");
}
});
}
И в initstate я вызываю эту функцию:
@override
void initState() {
updateDashboard();
super.initState();
}
Это работает, но, тем не менее, я понимаю, что ${this.user.points}
равен null
в течение нескольких секунд (я получаю этот экран с предупреждением), а затем он загружается и все в порядке. Я предполагаю, что это потому, что моя функция - async
... Но как я могу убедиться, что этот updateDashboard()
вызывается перед рендерингом Widget build()
?
4 ответа
Если вы не хотите использовать FutureBuilder
, вы можете сделать что-то вроде
if(done)
Column( /* whatever */ )
else
Center(child: CircularProgressIndicator())
void updateDashboard() async{
/* whatever */
if (res.statusCode == 200) {
setState(() {
this.user.setPoints(this.user.points);
done = true;
});
}
@override
void initState() {
/* whatever */
done = false;
}
Что ж, асинхронность означает, что загрузка данных может занять некоторое время и передается другому потоку для загрузки. Для этого может быть несколько неблокирующих способов:
Укажите значение по умолчанию для объекта
user
, поэтому к моменту завершения асинхронного метода вы увидите значения прокси / по умолчанию иsetState()
обеспечит отображение нового значения при загрузке.Этот метод требует, чтобы вы загружали виджеты условно, то есть загружайте виджет
Text
, когда есть данные, загружайтеContainer()
.
Пример для второго подхода:
this.user!=null?Text('${this.user.points}'):Container()
Таким образом, вам не нужно показывать виджет, пока не загрузится значение. Любой из подходов работает, и в зависимости от вашего варианта использования вы можете выбрать, какой из них вы можете применить.
Вы можете сделать загрузочную переменную, например, bool _loading
, тогда где бы вы ни начинали loading
свою функцию async
, вы можете setState
загрузить в true, а затем setState
из {{X5} } в false, когда функция async
перестает загружаться следующим образом.
void updateDashboard() async{
setState(() {
_loading = true;
});
SharedPreferences prefs = await SharedPreferences.getInstance();
var api_key = prefs.getString('api_key');
var userID = prefs.getInt('userID');
var res = await http.post(('http://myApp.com/getDashboardPreferences/'+userID.toString() + '/' + api_key),
headers: {
"Accept": "application/json",
"content-type": "application/json"
});
this.user = User.fromJson(json.decode(res.body));
setState(() {
if (res.statusCode == 200) {
this.user.setPoints(this.user.points);
} else {
print("Something is wrong");
}
_loading = false; //Set Loading to false
});
}
Затем в сборке вашего виджета проверьте, когда загрузка имеет значение true, и покажите индикатор прогресса, подобный этому.
body: _loading
? Center(
child: CircularProgressIndicator( //Show a Circular Progress indicator
valueColor: new AlwaysStoppedAnimation<Color>(Colors.cyan),
),
)
:Column(//Show your Dashboard)
Я надеюсь, что это помогает
Вы можете поставить функцию прямо перед возвращаемым виджетом.
Похожие вопросы
Новые вопросы
dart
Dart - это язык программирования, основанный на классах (статически и строго), для создания веб-приложений и мобильных приложений. Dart компилирует в современный JavaScript для запуска в браузере и компилирует в собственный код для запуска на мобильных платформах, таких как Android и iOS. Дарт также работает в командной строке для сценариев и приложений на стороне сервера.