You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter天气应用请求返回404且数据为Null问题求助

天气应用404错误及Null返回问题

跟着Udemy平台的Flutter入门课程开发天气应用,前期运行正常,完成当前章节后应用返回Null。热重启后日志显示404状态码及null,更换新API Key后问题依旧,课程较老旧无人答疑。

错误日志

Performing hot restart...
Syncing files to device moto g52...
Restarted application in 2,126ms.
I/flutter (13494): 404
I/flutter (13494): null

相关代码文件

main.dart

import 'package:clima/screens/location_screen.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(),
    );
  }
}

location_screen.dart

import 'package:flutter/material.dart';
import 'package:clima/utilities/constants.dart';

class LocationScreen extends StatefulWidget {
  LocationScreen({this.locationWeather});
  final locationWeather;

  @override
  _LocationScreenState createState() => _LocationScreenState();
}
class _LocationScreenState extends State<LocationScreen> {
  @override
  void initState() {
    super.initState();
    print(widget.locationWeather);
  }
@override
  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>[
                  TextButton(
                    onPressed: () {},
                    child: Icon(
                      Icons.near_me,
                      size: 50.0,
                    ),
                  ),
                  TextButton(
                    onPressed: () {},
                    child: Icon(
                      Icons.location_city,
                      size: 50.0,
                    ),
                  ),
                ],
              ),
              Padding(
                padding: EdgeInsets.only(left: 15.0),
                child: Row(
                  children: <Widget>[
                    Text(
                      '32°',
                      style: kTempTextStyle,
                    ),
                    Text(
                      '☀️',
                      style: kConditionTextStyle,
                    ),
                  ],
                ),
              ),
              Padding(
                padding: EdgeInsets.only(right: 15.0),
                child: Text(
                    "It's 🍦 time in San Francisco!",
                    textAlign: TextAlign.right,
                    style: kMessageTextStyle,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

loading_screen.dart

import 'package:clima/screens/location_screen.dart';
import 'package:flutter/material.dart';
import 'package:clima/services/location_handler.dart';
import 'package:clima/services/networking.dart';
import 'location_screen.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';

const myAPI = '7c8b4449639ae2b6b5e3bfd67a0e350f';

class LoadingScreen extends StatefulWidget {
  @override
  _LoadingScreenState createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen> {
  late double latitood;
  late double longitood;

  void initState() {
    super.initState();
    getLocationData();
  }

  void getLocationData() async {
    Locator loca = Locator();
    await loca.getCurrentLocation();
    latitood = loca.latitude;
    longitood = loca.longitude;

    NetworkHelper NetHelp = NetworkHelper(
        'https://api.openweathermap.org/data/2.5.weather?lat=$latitood&lon=$longitood&appid=$myAPI');
    var weatherDataFinal = await NetHelp.getData();

    Navigator.push(context, MaterialPageRoute(builder: (context) {
      return LocationScreen(
          locationWeather:
              weatherDataFinal); //creating a path to location_screen.dart
      //and passing/pushing weather data to location screen through a constructor.
    }));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SpinKitDoubleBounce(
          color: Colors.white,
          size: 100,
        ),
      ),
    );
  }
}

networking.dart

import 'dart:convert'; //imported to convert/use JSON data into our project.
import 'package:http/http.dart' as http;
class NetworkHelper {
  NetworkHelper(this.url);
  final String url;
  Future getData() async {
    http.Response response = await http.get(Uri.parse(url));
    //Passing the 'url' which is a String, will be converted into URI using 'Uri.parse' method.
    if (response.statusCode == 200) {
      String data = response.body;
      var decodedData = jsonDecode(data);
      //decoding and putting data into decodedData variable of dynamic type.
      return decodedData;
    } else {
      print(response.statusCode);
      print('Something\'s wrong I can feel it.');
    }
  }
}

location_handler.dart

import 'package:geolocator/geolocator.dart';

class Locator {    

  late double latitude;
  late double longitude;

  Future<void> getCurrentLocation() async {
    try {
      Position posi = await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.low);
      latitude = posi.latitude;
      longitude = posi.longitude;
    } on Exception catch (e) {
      print(e);
    }
  }
}

依赖包

  • geolocator: ^7.0.2
  • http: ^0.13.1
  • flutter_spinkit: ^5.1.0

问题排查与解决方案

1. 核心问题:API请求URL格式错误

404错误直接指向请求路径无效,查看loading_screen.dart中的API URL:
原路径为https://api.openweathermap.org/data/2.5.weather?lat=...
正确的OpenWeatherMap API路径应为https://api.openweathermap.org/data/2.5/weather?lat=...
修正方法:将URL中的2.5.weather改为2.5/weather

2. 完善位置获取的异常处理

当前location_handler.dart中,若位置获取失败,latitude和longitude作为late变量未被初始化,会导致后续请求出现非法参数。
优化代码:

class Locator {    
  double? latitude;
  double? longitude;

  Future<void> getCurrentLocation() async {
    try {
      Position posi = await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.low);
      latitude = posi.latitude;
      longitude = posi.longitude;
    } on Exception catch (e) {
      print(e);
      latitude = null;
      longitude = null;
    }
  }
}

同时在loading_screen.dart中添加位置校验:

void getLocationData() async {
  Locator loca = Locator();
  await loca.getCurrentLocation();
  if(loca.latitude == null || loca.longitude == null){
    print("无法获取位置信息");
    return;
  }
  latitood = loca.latitude!;
  longitood = loca.longitude!;
  // 后续请求代码...
}

3. 处理网络请求的错误返回

networking.dart中,非200状态码时未返回值,导致weatherDataFinal为null,传递到LocationScreen后打印null。
优化代码:

Future getData() async {
  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);
    print('请求失败');
    return null; // 显式返回null
  }
}

内容的提问来源于stack exchange,提问作者Sagar Jadhav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:10:49