我想用Flutter做一个天气应用程序。但是由于某些原因,()方法在initState之前运行()方法完成。问题是,所有的状态变量都使用setState初始化initState内部的()方法(),其变量将在生成中使用()方法。我猜问题是Flutter试图在setState()方法之前访问那些状态变量,这一直向我抛出错误:一个非空字符串必须提供给一个文本部件。我知道这些代码太长阅读。但我会很感激,如果你能帮助我。
import 'package:flutter/material.dart';
import "package:climat/screens/LoadingScreen.dart";
import "package:climat/screens/MainScreen.dart";
import "package:climat/screens/SearchScreen.dart";
void main() {
runApp(
MaterialApp(
theme: ThemeData(
fontFamily: "Open Sans",
),
title: "Climat",
initialRoute: "/",
onGenerateRoute: (RouteSettings routeSettings) {
dynamic routes = <String, WidgetBuilder>{
"/": (context) => LoadingScreen(),
"/index": (context) => MainScreen(),
"/search": (context) => SearchScreen(),
};
WidgetBuilder builder = routes[routeSettings.name];
return MaterialPageRoute(builder: (context) => builder(context));
},
),
);
}
import "package:flutter/material.dart";
import "package:flutter_spinkit/flutter_spinkit.dart";
import "package:climat/services/GeolocatorHelper.dart";
import "package:climat/services/NetworkHelper.dart";
import "package:climat/utilities/constants.dart";
class LoadingScreen extends StatefulWidget {
@override
_LoadingScreenState createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
Future<void> getWeatherData() async {
Map<String, double> coordinates = await GeolocatorHelper().getGeoData();
final NetworkHelper networkHelper = NetworkHelper(
uri:
"$endPoint&lat=${coordinates["latitude"]}&lon=${coordinates["longitude"]}");
final dynamic data = await networkHelper.getData();
return await Navigator.pushNamed(context, "/index", arguments: data);
}
@override
void initState() {
this.getWeatherData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Climat"),
),
body: SafeArea(
child: Center(
child: SpinKitRing(
color: Colors.redAccent,
),
),
),
);
}
}
import "package:flutter/material.dart";
import "package:climat/services/WeatherHelper.dart";
import "package:climat/services/NetworkHelper.dart";
import "package:climat/utilities/constants.dart";
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
Color backgroundColor;
String cityName;
int temperature;
String status;
String image;
int minTemperature;
int maxTemperature;
int humidity;
Future<void> updateUI({String userInput = null}) async {
dynamic weatherData;
if (userInput == null) {
weatherData = ModalRoute.of(context).settings.arguments;
} else {
final NetworkHelper networkHelper =
NetworkHelper(uri: "$endPoint&q=$userInput");
weatherData = await networkHelper.getData();
}
final int weatherCode = weatherData["weather"][0]["id"];
final WeatherHelper weatherHelper = WeatherHelper(
weatherCode: weatherCode,
);
setState(() {
this.backgroundColor = weatherHelper.getBackgroundColor();
this.cityName = weatherData["name"];
this.temperature = weatherData["main"]["temp"].toInt();
this.status = weatherHelper.getWeatherStatus();
this.minTemperature = weatherData["main"]["temp_min"].toInt();
this.maxTemperature = weatherData["main"]["temp_max"].toInt();
this.humidity = weatherData["main"]["humidity"];
this.image = weatherHelper.getWeatherImage();
});
}
@override
void initState() {
this.updateUI();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: this.backgroundColor,
appBar: AppBar(
title: Text("Climat"),
),
body: SafeArea(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
this.cityName,
style: TextStyle(
fontSize: 24.0,
color: Colors.white,
),
),
SizedBox(
height: 30.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
"./assets/images/${this.image}",
scale: 4.0,
),
SizedBox(
width: 30.0,
),
Text(
"${this.temperature}°C",
style: TextStyle(
fontSize: 96.0,
color: Colors.white,
),
),
],
),
SizedBox(
height: 30.0,
),
Text(
this.status.toUpperCase(),
style: TextStyle(
fontSize: 24.0,
color: Colors.white,
),
),
SizedBox(
height: 10.0,
),
Text(
"MIN / MAX : ${this.minTemperature.toString()} / ${this.maxTemperature.toString()}",
style: TextStyle(
fontSize: 24.0,
color: Colors.white,
),
),
SizedBox(
height: 10.0,
),
Text(
"HUMIDITY : ${this.humidity}%",
style: TextStyle(
fontSize: 24.0,
color: Colors.white,
),
),
SizedBox(
height: 30.0,
),
ElevatedButton(
onPressed: () async {
dynamic userInput =
await Navigator.pushNamed(context, "/search");
this.updateUI(
userInput: userInput.toString(),
);
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 16.0,
),
),
child: Text(
"Search by city name",
style: TextStyle(
fontSize: 20.0,
),
),
),
],
),
),
),
);
}
}
1条答案
按热度按时间py49o6xq1#
如果您希望在
initState
中使用Future
函数,并希望它在build
之前运行一次并完成,请考虑使用WidgetsBinding.instance.addPostFrameCallback
,例如以及
应使用
setState
重建小部件