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