错误:在构建期间调用setState()或markNeedsBuild()



我目前正在构建一个天气应用程序,为我们提供温度和气候信息(如果下雨或刮风或晴天)。我正在使用http和地理定位器包来构建我的应用程序。使用api密钥和json解码,我正在检索信息。

我得到以下错误

调试服务监听ws://127.0.0.1:57160/pspjoes2GlI=/ws

Error: setState() or markNeedsBuild() called during build.
This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets.  A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
Overlay-[LabeledGlobalKey<OverlayState>#044ff]
The widget which was currently being built when the offending call was made was:
Builder
at Object.throw_ [as throw] (http://localhost:64547/dart_sdk.js:5348:11)
at http://localhost:64547/packages/flutter/src/widgets/widget_span.dart.lib.js:29299:23
at framework.StatefulElement.new.markNeedsBuild (http://localhost:64547/packages/flutter/src/widgets/widget_span.dart.lib.js:29307:26)
at overlay$.OverlayState.new.setState (http://localhost:64547/packages/flutter/src/widgets/widget_span.dart.lib.js:17689:43)
at overlay$.OverlayState.new.rearrange (http://localhost:64547/packages/flutter/src/widgets/widget_span.dart.lib.js:31894:12)

我的代码

Main.dart

import 'package:flutter/material.dart';
import 'package:clima/screens/loading_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: LoadingScreen(),
);
}
}

LoadingScreen.dart

import 'package:flutter/material.dart';
import 'location_screen.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'dart:convert';
import'package:clima/services/weather.dart';
const APIkey = '9f2e463e61258ef5a8b9a9bd11733b62c';
class LoadingScreen extends StatefulWidget {
@override
_LoadingScreenState createState() => _LoadingScreenState();
}
double MyMarginAsDouble;
double latitude,longitude;
class _LoadingScreenState extends State<LoadingScreen> {
void initState(){//if i call getlocation inside init method it automatically gets the location without the need of a button
super.initState();
getLocationData();
}
Future<void> getLocationData()
async {
WeatherModel weatherModel = WeatherModel();
var weatherData = weatherModel.getLocationWeather();
Navigator.push(context,MaterialPageRoute(builder:(context){
return LocationScreen(
locationWeather: weatherData,//weather data links to networkHelper cls in networking.dart gets the weather info using http package
);
}
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body:Center(
child:SpinKitDoubleBounce(
color:Colors.white,
size:100,
)
)
);
}
}

Location_screen.dart

import 'dart:convert';
import 'package:clima/services/weather.dart';
import 'package:geolocator/geolocator.dart';
import 'package:flutter/material.dart';
import 'package:clima/utilities/constants1.dart';
import 'package:clima/services/weather.dart';
WeatherModel o = WeatherModel();
class LocationScreen extends StatefulWidget {
LocationScreen({this.locationWeather});//yow will be passed WeatherData variable (it contains the info of the weather retrieived frm the http api url) (WeatherData of the loading_Screen).
final locationWeather;//LocationWeather receives the information
@override
_LocationScreenState createState() => _LocationScreenState();
}
class _LocationScreenState extends State<LocationScreen> {
WeatherModel weather = WeatherModel();
int temperature;
double temp;
String weatherIcon;
int condition;
String cityName;
@override
void initState(){
super.initState();
updateUi(widget.locationWeather);
}
void updateUi(dynamic weatherData)
{
var condition = weatherData['weather'][0]['id'];//api contains id eg 300 for light drizzle and so on
temp = weatherData['main']['temp'];
temperature=temp.toInt();
cityName = weatherData['name'];
weatherIcon =weather.getWeatherIcon(condition);//pass that condition to a method in getWeatherdata
print(temperature);
}
Future<void> getLocation()
async {
LocationPermission permission = await Geolocator.requestPermission();
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
print(position);
}
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/location_background.jpg'),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.white.withOpacity(0.8), BlendMode.dstATop),
),
),
constraints: BoxConstraints.expand(),
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: () async {
var weatherData = await weather.getLocationWeather();//we need to gaurantee that this wont return null as it will take long time to execute
updateUi(weatherData);
},
child: Icon(
Icons.near_me,
size: 50.0,
),
),
FlatButton(
onPressed: () {},
child: Icon(
Icons.location_city,
size: 50.0,
),
),
],
),
Padding(
padding: EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
Text(
'$temperature°',
style: kTempTextStyle,
),
Text(
weatherIcon ,
style: kConditionTextStyle,
),
],
),
),
Padding(
padding: EdgeInsets.only(right: 15.0),
child: Text(
"${o.getMessage(temperature)}in $cityName!",//
textAlign: TextAlign.right,
style: kMessageTextStyle,
),
),
],
),
),
),
);
}
}

Location.dart

进口包:geolocator/geolocator.dart的;

class location{
double latitude;
double longitude;
Future  getCurrentLocation()
async {
try{
LocationPermission permission = await Geolocator.requestPermission();
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low); //high is battery consuming
LocationPermission permission1 = await Geolocator.checkPermission();
latitude=position.latitude;
longitude=position.longitude;
}
catch(e)
{
print(e);
}
}
}

Networking.dart

import 'package:http/http.dart' as http;
import 'dart:convert';
class NetworkHelper {
NetworkHelper(this.url);
var url;
Future getData() async {
//var url = Uri.parse(url);
//var url = Uri.parse('api.openweathermap.org/data/2.5/weather?q=London&appid=92e463e61258ef5a8b9a9bd11733b62c');
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
String data = response.body;
var decodedData = jsonDecode(data);
return decodedData;
}
else {
print(response.statusCode);
}
}
}

Weather.dart

import '../location.dart';
import 'networking.dart';
class WeatherModel {
Future getLocationWeather()
async {
location ob= new location();
await ob.getCurrentLocation();
print(ob.latitude);
print(ob.longitude);
//calling networkHelper
NetworkHelper networkHelper = NetworkHelper('http://api.openweathermap.org/data/2.5/weather?lat=${ob.latitude}&lon=${ob.longitude}&appid=92e463e61258ef5a8b9a9bd11733b62c&units=metric');
var WeatherData = await networkHelper.getData();
return WeatherData;
}
String getWeatherIcon(int condition) {
if (condition < 300) {
return '🌩';
} else if (condition < 400) {
return '🌧';
} else if (condition < 600) {
return '☔️';
} else if (condition < 700) {
return '☃️';
} else if (condition < 800) {
return '🌫';
} else if (condition == 800) {
return '☀️';
} else if (condition <= 804) {
return '☁️';
} else {
return '🤷‍';
}
}
String getMessage(int temp) {
if (temp > 25) {
return 'It's 🍦 time';
} else if (temp > 20) {
return 'Time for shorts and 👕';
} else if (temp < 10) {
return 'You'll need 🧣 and 🧤';
} else {
return 'Bring a 🧥 just in case';
}
}
}

city_Screen.dart

import 'package:flutter/material.dart';
import 'package:clima/utilities/constants1.dart';
class CityScreen extends StatefulWidget {
@override
_CityScreenState createState() => _CityScreenState();
}
class _CityScreenState extends State<CityScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/city_background.jpg'),
fit: BoxFit.cover,
),
),
constraints: BoxConstraints.expand(),
child: SafeArea(
child: Column(
children: <Widget>[
Align(
alignment: Alignment.topLeft,
child: FlatButton(
onPressed: () {},
child: Icon(
Icons.arrow_back_ios,
size: 50.0,
),
),
),
Container(
padding: EdgeInsets.all(20.0),
child: null,
),
FlatButton(
onPressed: () {},
child: Text(
'Get Weather',
style: kButtonTextStyle,
),
),
],
),
),
),
);
}
}

Conststants1.dart

import 'package:flutter/material.dart';
const kTempTextStyle = TextStyle(
fontFamily: 'Spartan MB',
fontSize: 100.0,
);
const kMessageTextStyle = TextStyle(
fontFamily: 'Spartan MB',
fontSize: 60.0,
);
const kButtonTextStyle = TextStyle(
fontSize: 30.0,
fontFamily: 'Spartan MB',
);
const kConditionTextStyle = TextStyle(
fontSize: 100.0,
);

像这样修改getLocationData方法:

getLocationData() async {
WeatherModel weatherModel = WeatherModel();
var weatherData = await weatherModel.getLocationWeather();
if (weatherData != null) {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return LocationScreen(
locationWeather: weatherData,
);
}));
}
}

最新更新