前言
在前一篇博客中,我们介绍了如何使用Flutter创建一个简单的天气预报应用程序。在这篇博客中,我们将进一步完善我们的应用,添加城市定位功能以及将地理位置转换为城市代码的功能。
获取当前位置
在获取当前位置的过程中,我们使用了Flutter的Geolocator库。这个库不仅仅可以获取设备的经纬度,还能提供更多有关设备位置的信息。例如,我们可以获取设备的海拔高度、速度、方向等。在实际应用中,根据需求可以灵活运用这些功能,比如实现高度相关的气象应用或运动追踪应用等。下面是获取当前位置的代码:
代码语言:javascript复制 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 地处理。
完成之后,我们输出获取到的地理位置信息,来看一看自己是否函数是否能够正常使用;下面编写一个函数来查看我们的输出:
代码语言:javascript复制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
请求后的内容如下:
代码语言:javascript复制{
"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最多只支持经纬度小数点后两位,所以在之前的定位过程中可以不用选择高精度。
代码语言:javascript复制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