Flutter如何实现监听定位开关状态的StreamBuilder
Flutter 定位服务状态实时监听StreamBuilder实现方案
依赖准备
在pubspec.yaml中添加定位插件依赖,该插件原生封装了系统定位服务状态的监听能力,无需自行编写原生桥接代码:
dependencies: flutter: sdk: flutter geolocator: ^11.0.0 # 可替换为当前最新稳定版本
执行flutter pub get拉取依赖后,按照插件说明完成Android、iOS端的定位权限配置,否则状态监听会出现异常。
核心代码实现
直接使用插件提供的定位服务状态流配合StreamBuilder即可实现自动联动,流由系统底层触发事件,用户手动开关定位时会即时推送最新状态,无需手动轮询。
import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; class LocationGuardPage extends StatelessWidget { const LocationGuardPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: StreamBuilder<ServiceStatus>( // 定位服务状态变化实时流 stream: Geolocator.getServiceStatusStream(), builder: (context, snapshot) { // 首次监听时流不会主动推送当前状态,主动查询一次定位开关状态避免空白 if (snapshot.connectionState == ConnectionState.waiting) { return FutureBuilder<bool>( future: Geolocator.isLocationServiceEnabled(), builder: (context, initSnapshot) { if (!initSnapshot.hasData) { return const Center(child: CircularProgressIndicator()); } return initSnapshot.data! ? const BusinessDataPage() : const LocationDisabledTipPage(); }, ); } // 流异常时展示错误提示 if (snapshot.hasError) { return Center(child: Text('定位状态获取失败: ${snapshot.error}')); } // 根据流推送的最新状态自动切换页面 return snapshot.data == ServiceStatus.enabled ? const BusinessDataPage() : const LocationDisabledTipPage(); }, ), ); } } // 定位开启时展示的业务数据页 class BusinessDataPage extends StatefulWidget { const BusinessDataPage({super.key}); @override State<BusinessDataPage> createState() => _BusinessDataPageState(); } class _BusinessDataPageState extends State<BusinessDataPage> { @override void initState() { super.initState(); // 页面进入时可直接触发定位、拉取业务数据等逻辑 } @override Widget build(BuildContext context) { return const Center( child: Text('定位服务正常,此处展示业务数据内容'), ); } } // 定位关闭时展示的提示页 class LocationDisabledTipPage extends StatelessWidget { const LocationDisabledTipPage({super.key}); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.location_off, size: 80, color: Colors.grey), const SizedBox(height: 16), const Text( '定位服务未开启', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500), ), const SizedBox(height: 8), const Text('请开启设备定位服务后使用本功能'), const SizedBox(height: 24), ElevatedButton( onPressed: () async { // 可选:点击按钮直接跳转系统定位设置页 await Geolocator.openLocationSettings(); }, child: const Text('前往开启定位'), ) ], ), ); } }
关键说明
StreamBuilder会自动管理流的订阅与销毁,页面退出时自动取消监听,不会造成内存泄漏- 系统定位开关状态变化的回调是底层触发的,没有轮询带来的性能损耗,状态切换延迟在100ms以内,用户感知不到卡顿
- 若需要在定位状态切换时做额外逻辑(比如定位开启后自动刷新位置数据),可直接在
BusinessDataPage的生命周期方法中编写对应逻辑,状态切换时页面会自动重建触发执行 - 注意不要混淆定位权限状态和定位服务开关状态:前者是用户给APP的定位授权,后者是系统全局的定位功能开关,上述实现监听的是系统全局定位开关状态
内容的提问来源于stack exchange,提问作者Dhaval Chaudhari
相关产品推荐
相关产品推荐

