Flutter weather api 显示错误类型 'Null' is not a subtype of type 'Weather'

Flutter weather api shows error type 'Null' is not a subtype of type'Weather'

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_project/currentWeather.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: CurrentWeatherPage(),
    );
  }
}

models/weather.飞镖

class Weather{
  final double temp;
  final double feelsLike;
  final double low;
  final double high;
  final String description;

  Weather({ required this.temp, required this.feelsLike, required this.low, required this.high, required this.description});

  factory Weather.fromJson(Map<String,dynamic>json){
    return Weather(
      temp: json['main']['temp'].toDouble(),
      feelsLike: json['main']['feels_like'].toDouble(),
      low: json['main']['temp_min'].toDouble(),
      high: json['main']['temp_max'].toDouble(),
      description: json['weather'][0]['description'],
    );
  }
}

currentWeather.dart

import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'models/weather.dart';

class CurrentWeatherPage extends StatefulWidget {
  const CurrentWeatherPage({ Key? key }) : super(key: key);

  @override
  State<CurrentWeatherPage> createState() => _CurrentWeatherPageState();
}

class _CurrentWeatherPageState extends State<CurrentWeatherPage> {
  late final Weather _weather;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: FutureBuilder(
            builder: (context, AsyncSnapshot snapshot) {
              // ignore: unnecessary_null_comparison
              if (snapshot != null) {
                Weather _weather = snapshot.data;
                // ignore: unnecessary_null_comparison
                if (_weather == null) {
                  return const Text("Error getting weather");
                } else {
                  return  weatherBox(_weather);
                }
              } else {
                return const CircularProgressIndicator();
              }
            },
          future: getCurrentWeather(),
        ),
      )
    );
  }
}

Widget weatherBox(Weather _weather) {
  
  return Column(
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
      Container(
          margin: const EdgeInsets.all(10.0),
          child: 
          Text("${_weather.temp}°C",
            textAlign: TextAlign.center,
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 55),
          )
        ),
        Container(
          margin: const EdgeInsets.all(5.0),
          child: Text("${_weather.description}")
        ),
        Container(
          margin: const EdgeInsets.all(5.0),
          child: Text("Feels:${_weather.feelsLike}°C")
        ),
        Container(
          margin: const EdgeInsets.all(5.0),
          child: Text("H:${_weather.high}°C L:${_weather.low}°C")
        ),
    ]
  
  );  
}

Future getCurrentWeather() async {
  late Weather weather;
  String city = "karak,my";
  String apiKey = "saasfdglkoqn";
  var url = Uri.parse("https://api.openweathermap.org/data/2.5/weather?q=$city&appid=$apiKey&units=metric");

  final response = await http.get(url);

  if (response.statusCode == 200) {
    weather = Weather.fromJson(jsonDecode(response.body));
  } 
  return weather;
}

在 运行

期间收到此错误

小部件库捕获异常

类型 'Null' 不是类型 'Weather'

的子类型

导致错误的相关小部件是

FutureBuilder 动态

我该如何解决这个问题? 我能知道这个错误背后的原因吗?一段时间以来我一直在努力解决这个问题,请帮我解决一下。提前致谢

API 需要密钥。

{
  cod: 401,
  message: "Invalid API key. Please see http://openweathermap.org/faq#error401 for more info."
}

当API returns 不正常时抛出异常。

Future<Weather> getCurrentWeather() async {
  late Weather weather;
  String city = "karak,my";
  String apiKey = "saasfdglkoqn";
  var url = Uri.parse("https://api.openweathermap.org/data/2.5/weather?q=$city&appid=$apiKey&units=metric");

  final response = await http.get(url);

  if (response.statusCode == 200) {
    weather = Weather.fromJson(jsonDecode(response.body));
  } else {
    throw Exception(response.body);
  }
  return weather;
}

A​​syncSnapshot 具有属性 hasData 和 hasError 来检查状态。

      body: Center(
          child: FutureBuilder(
            builder: (context, AsyncSnapshot snapshot) {
              if (snapshot.hasData) {
                return  weatherBox(snapshot.data);
              } else if (snapshot.hasError) {
                return Text(snapshot.error.toString());
              } else {
                return const CircularProgressIndicator();
              }
            },
          future: getCurrentWeather(),
        ),