Flutter地理编码插件osm_geocoder的使用

Flutter地理编码插件osm_geocoder的使用

地图编码插件osm_geocoder 可以帮助你在Flutter应用中获取地理信息。它无需API密钥即可获得详细的位置数据,并且使用的是 Open Street Map 的数据。


获取坐标位置数据

使用坐标从Open Street Map获取位置数据非常简单:

Coordinates coordinates = Coordinates(-5.837799, -35.203978);
LocationData data = await OSMGeocoder.findDetails(coordinates);

LocationData

LocationData 类包含以下字段:

int placeId;
String osmType;
int id;
String lat;
String lon;
int placeRank;
double importance;
String displayName;
Address address;
List<String> boundingbox;

Address

Address 类提供了详细的地址信息:

String road;
String suburb;
String city;
String stateDistrict;
String state;
String iso31662Lvl4;
String postcode;
String country;
String countryCode;

更多详细信息,请参阅文档。


关于OpenStreetMap

OpenStreetMap 是一个协作项目,旨在创建和分发免费的地理数据,这些数据没有法律或技术限制,可以自由使用。

该项目已有20年的历史,目前正处于其第6版API阶段,并在包括巴西在内的多个国家设有子项目。


完整示例代码

以下是完整的示例代码,展示了如何在Flutter应用中使用osm_geocoder插件来搜索地址并显示结果:

import 'package:flutter/material.dart';
import 'package:osm_geocoder/osm_geocoder.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'OSM Geocoder Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const DemoGeocoderPage(title: 'OSM Geocoder Demo'),
    );
  }
}

class DemoGeocoderPage extends StatefulWidget {
  const DemoGeocoderPage({super.key, required this.title});
  final String title;

  [@override](/user/override)
  State<DemoGeocoderPage> createState() => _DemoGeocoderPageState();
}

class _DemoGeocoderPageState extends State<DemoGeocoderPage> {
  final TextEditingController _controller = TextEditingController(text: 'UFRN');
  List<MapData> _result = [];
  bool _isLoading = false;

  Future<void> _searchAddress() async {
    final query = _controller.text;

    setState(() {
      _isLoading = true;
    });

    try {
      final result = await OSMGeocoder.query(query);
      setState(() {
        _result = result;
        _isLoading = false;
      });
    } catch (e) {
      setState(() {
        _isLoading = false;
      });

      print("Error: $e");
    }
  }

  [@override](/user/override)
  void initState() {
    super.initState();
    _searchAddress();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(children: [
          TextField(
            controller: _controller,
            decoration: InputDecoration(
              labelText: 'Search address:',
              border: const OutlineInputBorder(),
              suffixIcon: IconButton(
                  autofocus: true,
                  onPressed: _searchAddress,
                  icon: const Icon(Icons.search)),
            ),
          ),
          const SizedBox(height: 16.0),
          _isLoading
              ? const CircularProgressIndicator()
              : Expanded(
                  child: ListView.builder(
                      itemCount: _result.length,
                      itemBuilder: (context, index) {
                        final address = _result[index];
                        return Padding(
                          padding: const EdgeInsets.only(bottom: 16.0),
                          child: ListTile(
                            leading: const Icon(Icons.location_on),
                            tileColor:
                                Theme.of(context).colorScheme.primaryContainer,
                            iconColor:
                                Theme.of(context).colorScheme.inversePrimary,
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(16.0),
                            ),
                            title: Text(address.displayName),
                            subtitle: Text(
                                "Lat: ${address.lat} | Lon: ${address.lon}"),
                          ),
                        );
                      }),
                ),
        ]),
      ),
    );
  }
}

更多关于Flutter地理编码插件osm_geocoder的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地理编码插件osm_geocoder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


osm_geocoder 是一个用于在 Flutter 中进行地理编码的插件,它使用 OpenStreetMap 的 Nominatim 服务来进行地理编码和反向地理编码。地理编码是将地址转换为地理坐标(纬度和经度)的过程,而反向地理编码则是将地理坐标转换为地址。

1. 安装插件

首先,你需要在 pubspec.yaml 文件中添加 osm_geocoder 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  osm_geocoder: ^1.0.0  # 请检查最新版本

然后运行 flutter pub get 来安装插件。

2. 基本用法

地理编码(地址转坐标)

import 'package:osm_geocoder/osm_geocoder.dart';

void geocodeAddress() async {
  final geocoder = OsmGeocoder();

  try {
    final coordinates = await geocoder.geocode('1600 Amphitheatre Parkway, Mountain View, CA');
    print('Latitude: ${coordinates.latitude}');
    print('Longitude: ${coordinates.longitude}');
  } catch (e) {
    print('Error: $e');
  }
}

反向地理编码(坐标转地址)

import 'package:osm_geocoder/osm_geocoder.dart';

void reverseGeocode() async {
  final geocoder = OsmGeocoder();

  try {
    final address = await geocoder.reverseGeocode(37.4219999, -122.0840575);
    print('Address: $address');
  } catch (e) {
    print('Error: $e');
  }
}

3. 配置和限制

osm_geocoder 使用 OpenStreetMap 的 Nominatim 服务,因此你需要遵守 Nominatim 的使用政策。具体来说,Nominatim 对请求频率有严格的限制,通常为每秒 1 次请求。如果你需要更高的请求频率,可以申请 API 密钥或使用其他地理编码服务。

4. 错误处理

在调用 geocodereverseGeocode 方法时,可能会抛出异常,例如网络错误或地址找不到。你可以使用 try-catch 块来捕获并处理这些异常。

5. 其他注意事项

  • 隐私:OpenStreetMap 的 Nominatim 服务是基于开源数据的,因此在使用时需要注意隐私问题,避免频繁请求或滥用。
  • 缓存:为了提高性能,你可以考虑在应用层面对地理编码结果进行缓存,以减少对 Nominatim 服务的请求。

6. 示例

以下是一个完整的示例,展示了如何在一个简单的 Flutter 应用中使用 osm_geocoder 进行地理编码和反向地理编码:

import 'package:flutter/material.dart';
import 'package:osm_geocoder/osm_geocoder.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('OSM Geocoder Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () async {
                  final geocoder = OsmGeocoder();
                  try {
                    final coordinates = await geocoder.geocode('1600 Amphitheatre Parkway, Mountain View, CA');
                    print('Latitude: ${coordinates.latitude}');
                    print('Longitude: ${coordinates.longitude}');
                  } catch (e) {
                    print('Error: $e');
                  }
                },
                child: Text('Geocode Address'),
              ),
              ElevatedButton(
                onPressed: () async {
                  final geocoder = OsmGeocoder();
                  try {
                    final address = await geocoder.reverseGeocode(37.4219999, -122.0840575);
                    print('Address: $address');
                  } catch (e) {
                    print('Error: $e');
                  }
                },
                child: Text('Reverse Geocode'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
回到顶部