Flutter 多端天气预报APP第二弹 —— 城市定位以及城市代码的转换

举报
繁依Fanyi 发表于 2024/12/22 20:49:50 2024/12/22
【摘要】 前言在前一篇博客中,我们介绍了如何使用Flutter创建一个简单的天气预报应用程序。在这篇博客中,我们将进一步完善我们的应用,添加城市定位功能以及将地理位置转换为城市代码的功能。最近想搞私域,欢迎各位大佬光临😀😀😀! 获取当前位置在获取当前位置的过程中,我们使用了Flutter的Geolocator库。这个库不仅仅可以获取设备的经纬度,还能提供更多有关设备位置的信息。例如,我们可以获...

前言

在前一篇博客中,我们介绍了如何使用Flutter创建一个简单的天气预报应用程序。在这篇博客中,我们将进一步完善我们的应用,添加城市定位功能以及将地理位置转换为城市代码的功能。

最近想搞私域,欢迎各位大佬光临😀😀😀!

在这里插入图片描述

获取当前位置

在获取当前位置的过程中,我们使用了Flutter的Geolocator库。这个库不仅仅可以获取设备的经纬度,还能提供更多有关设备位置的信息。例如,我们可以获取设备的海拔高度、速度、方向等。在实际应用中,根据需求可以灵活运用这些功能,比如实现高度相关的气象应用或运动追踪应用等。下面是获取当前位置的代码:

  Future<Position?> getCurrentLocation() async {
    try {
      return await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    } catch (e) {
      // 处理定位失败的情况
      print("Error getting location: $e");
      return null;
    }
  }

这个函数通过Geolocator.getCurrentPosition方法获取设备的当前位置,desiredAccuracy参数用于指定定位的精确度。我们通过try-catch块捕获异常,以确保在定位失败时能够 graceful 地处理。

完成之后,我们输出获取到的地理位置信息,来看一看自己是否函数是否能够正常使用;下面编写一个函数来查看我们的输出:

Future<void> printCurrentLocation() async{

    try {

      Position? position = await Geolocator.getCurrentPosition();
      print(position);
    } catch (error) {
      print('Error fetching weather data: $error');
      // 处理异常,显示错误信息
    }
  }

可以看到,控制台可以正常输出我们的位置。

在这里插入图片描述

当前位置经纬度转 Location ID

获得当前位置的经纬度后,我们要将其转换为可用于和风天气API的城市代码,这样才能够填充之前请求天气的 location 参数。下面是我找到的和风天气的经纬度转城市代码的api,

https://geoapi.qweather.com/v2/city/lookup?location=116.41,39.92&key=$apiKeye

请求后的内容如下:

{
    "code": "200",
    "location": [
        {
            "name": "东城",
            "id": "101011600",
            "lat": "39.91755",
            "lon": "116.41876",
            "adm2": "北京",
            "adm1": "北京市",
            "country": "中国",
            "tz": "Asia/Shanghai",
            "utcOffset": "+08:00",
            "isDst": "0",
            "type": "city",
            "rank": "35",
            "fxLink": "https://www.qweather.com/weather/dongcheng-101011600.html"
        }
    ],
    "refer": {
        "sources": [
            "QWeather"
        ],
        "license": [
            "QWeather Developers License"
        ]
    }
}

简要把各个字段列成表格,表格中 location 属性下的 id 就是我们想要的内容:

字段 描述
code API响应的状态码。
location 包含有关位置的详细信息的数组。
- name 位置的名称(例如:“东城”)。
- id 位置的唯一标识符(例如:“101011600”)。
- lat 位置的纬度坐标(例如:“39.91755”)。
- lon 位置的经度坐标(例如:“116.41876”)。
- adm2 行政区划级别2(例如:“北京”)。
- adm1 行政区划级别1(例如:“北京市”)。
- country 位置所在国家(例如:中国)。
- tz 位置的时区(例如:“Asia/Shanghai”)。
- utcOffset 位置的UTC偏移量(例如:"+08:00")。
- isDst 夏令时指示符(例如:"0"表示无夏令时)。
- type 位置的类型(例如:“city”)。
- rank 位置的排名(例如:“35”)。
- fxLink 查看位置天气详情的链接。
refer 附加信息和参考资料。
- sources 数据来源数组(例如:[“QWeather”])。
- license QWeather开发者许可证信息。

编写代码通过 api 将经纬度转换成 location id。提醒一下大家,和风天气的这个api最多只支持经纬度小数点后两位,所以在之前的定位过程中可以不用选择高精度。

Future<String?> getCityCodeFromLocation() async{

    try {
      // 经纬度
      String latitude = "39.91";
      String longitude = "116.41";

      Position? position = await Geolocator.getCurrentPosition();
      latitude = position.latitude.toStringAsFixed(2);
      longitude = position.longitude.toStringAsFixed(2);

      // 构建 API 请求的 URL
      String apiUrl =
          'https://geoapi.qweather.com/v2/city/lookup?location=$longitude,$latitude&key=$apiKey';

      // 发送 HTTP GET 请求
      http.Response response = await http.get(Uri.parse(apiUrl));

      if (response.statusCode == 200) {
        // 解析 JSON 响应
        Map<String, dynamic> data = json.decode(response.body);

        // 获取 Location ID
        String locationId = data['location'][0]['id'].toString();
        print(locationId);	// 输出一下看看
        return locationId;
        
      } else {
        print("Error getting Location ID");
        return null;
      }
    } catch (e) {
      
      print("Error getting Location ID");
      return null;
      
    }
  }

通过http库发送HTTP GET请求到和风天气的城市查询API,获取对应经纬度的城市信息,并提取出城市代码。运行后可以看到输出的城市代码:

在这里插入图片描述

然后再传回到 getWeatherData() 中,

Future<Map<String, dynamic>> getWeatherData() async {


    String? locationId = await getCityCodeFromLocation();
    String url = 'https://devapi.qweather.com/v7/weather/3d?location=$locationId&key=$apiKey';
    Uri uri = Uri.parse(url);
    var response = await http.get(uri);

    if (response.statusCode == 200) {
      return json.decode(response.body);
    } else {
      throw Exception('Failed to load weather data');
    }
  }

编译运行一下,和我所在位置的气候一模一样,Success😀!

在这里插入图片描述

结语

在本博客中,我们详细介绍了如何使用Geolocator库获取设备当前位置,以及如何将地理位置转换为城市代码。这些功能不仅提升了用户体验,还使得我们的应用更具实用性。在下一篇博客中,我们将探讨在Android应用中可能涉及的权限问题,以及如何处理这些权限。

后面,可能还会考虑一些实际应用,比如频繁地请求同一位置的天气信息可能是不必要的。可以考虑使用缓存机制,将已经获取到的天气信息存储在本地,避免重复请求。这既能提高应用的性能,又能减轻服务器负担。

希望这篇博客对你有所帮助。如果你有任何问题或建议,请随时留言。感谢你的阅读!

作者信息

作者 : 繁依Fanyi
CSDN: https://techfanyi.blog.csdn.net
掘金:https://juejin.cn/user/4154386571867191
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。