即使位置是静态的(颤振),位置 onChange 函数也会不断被调用

Posted

技术标签:

【中文标题】即使位置是静态的(颤振),位置 onChange 函数也会不断被调用【英文标题】:location onChange function keeps getting called even when location is static (Flutter) 【发布时间】:2020-03-29 20:07:09 【问题描述】:

我正在使用 Flutter 中的 Location 3.0.1 包。我想听位置变化。我的代码(几乎完全取自这个包的 github 示例)如下:

class _HomePageState extends State<HomePage> 
  StreamSubscription<LocationData> locationSubscription;
  final Location location = new Location();
  LocationData _locationData;
  String _error;
  var popupData;

  PermissionStatus _permissionGranted;

  _checkPermissions() async 
    PermissionStatus permissionGrantedResult = await location.hasPermission();
    setState(() 
      _permissionGranted = permissionGrantedResult;
    );
  

  _requestPermission() async 
    if (_permissionGranted != PermissionStatus.GRANTED) 
      PermissionStatus permissionRequestedResult =
      await location.requestPermission();
      print(permissionRequestedResult);
      setState(() 
        _permissionGranted = permissionRequestedResult;
      );
      if (permissionRequestedResult != PermissionStatus.GRANTED) 
        return;
       else
        _loadLocation();
      
    
    else
      _loadLocation();
    
  

  Future<void> _listenLocation() async 
    locationSubscription =
        location.onLocationChanged().handleError((dynamic err) 
          setState(() 
            _error = err.code;
          );
          locationSubscription.cancel();
        ).listen((LocationData currentLocation) 
          setState(() 
            _error = null;

            _locationData = currentLocation;
          );
        );
  

  void _loadLocation() async 
    _locationData = await location.getLocation();
    _listenLocation();
  

  void initState() 
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    if(_locationData == null)
      _checkPermissions();
      _requestPermission();
    
.  .  .

但是,即使位置没有改变(我是在我的模拟器上运行此代码,因此位置应该是静态的)。有谁知道为什么会发生这种情况以及如何解决?

颤振医生的输出:

[✓] Flutter (Channel stable, v1.12.13+hotfix.5, on Mac OS X 10.15.2 19C57, locale en-US)
    • Flutter version 1.12.13+hotfix.5 at /Users/foo/development/flutter
    • Framework revision 27321ebbad (4 months ago), 2019-12-10 18:15:01 -0800
    • Engine revision 2994f7e1e6
    • Dart version 2.7.0


[✓] android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at /Users/foo/Library/Android/sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 28.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    • All Android licenses accepted.

[✓] Xcode - develop for ios and macOS (Xcode 11.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.3, Build version 11C29
    • CocoaPods version 1.8.4

[✓] Android Studio (version 3.5)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 39.0.3
    • Dart plugin version 191.8423
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[✓] IntelliJ IDEA Ultimate Edition (version 2019.1.4)
    • IntelliJ at /Applications/IntelliJ IDEA.app
    • Flutter plugin version 38.1.3
    • Dart plugin version 191.8593

[✓] Connected device (2 available)
    • Android SDK built for x86 • emulator-5554                        • android-x86 • Android 9 (API 28) (emulator)
    • iPhone 11 Pro Max         • B3536B50-C435-4442-9CF4-69D470B979CA • ios         •
      com.apple.CoreSimulator.SimRuntime.iOS-13-3 (simulator)

• No issues found!

如果有人可以给我一段代码,展示如何正确侦听更新,那也会很有帮助(即我的代码看起来并不像这样)。

【问题讨论】:

【参考方案1】:

您可以在下面复制粘贴运行完整代码 因为您将代码放在 Widget build 中导致此问题 您可以参考此https://medium.com/flutter-community/build-a-location-service-in-flutter-367a1b212f7a 来构建位置服务 我做了一些改动,你可以直接看到完整的代码 您可以在Widget build 中使用StreamProvider 而不是await location.getLocation 你可以直接用location.requestPermission代替Permission Handler

代码片段

return StreamProvider<UserLocation>(
  create: (context) => LocationService().locationStream,
...
LocationService() 
    // Request permission to use location
    location.requestPermission().then((permissionStatus) 
      if (permissionStatus == PermissionStatus.granted) 
        // If granted listen to the onLocationChanged stream and emit over our controller
        location.onLocationChanged.listen((locationData) 

工作演示

完整代码

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:location/location.dart';
import 'dart:async';

class LocationService 
  UserLocation _currentLocation;

  var location = Location();
  StreamController<UserLocation> _locationController =
      StreamController<UserLocation>();

  Stream<UserLocation> get locationStream => _locationController.stream;

  LocationService() 
    // Request permission to use location
    location.requestPermission().then((permissionStatus) 
      if (permissionStatus == PermissionStatus.granted) 
        // If granted listen to the onLocationChanged stream and emit over our controller
        location.onLocationChanged.listen((locationData) 
          if (locationData != null) 
            _locationController.add(UserLocation(
              latitude: locationData.latitude,
              longitude: locationData.longitude,
            ));
          
        );
      
    );
  

  Future<UserLocation> getLocation() async 
    try 
      var userLocation = await location.getLocation();
      _currentLocation = UserLocation(
        latitude: userLocation.latitude,
        longitude: userLocation.longitude,
      );
     on Exception catch (e) 
      print('Could not get location: $e.toString()');
    

    return _currentLocation;
  


void main() 
  runApp(MyApp());


class UserLocation 
  final double latitude;
  final double longitude;

  UserLocation(this.latitude, this.longitude);


class MyApp extends StatelessWidget 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) 
    return StreamProvider<UserLocation>(
      create: (context) => LocationService().locationStream,
      child: MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            body: HomeView(),
          )),
    );
  


class HomeView extends StatelessWidget 
  const HomeView(Key key) : super(key: key);

  @override
  Widget build(BuildContext context) 
    var userLocation = Provider.of<UserLocation>(context);
    return Center(
      child: Text(
          'Location: Lat$userLocation?.latitude, Long: $userLocation?.longitude'),
    );
  

【讨论】:

以上是关于即使位置是静态的(颤振),位置 onChange 函数也会不断被调用的主要内容,如果未能解决你的问题,请参考以下文章

使用颤振位置插件在 Android 中自动添加后台位置权限

在我的颤振应用中打开位置坐标

颤振:“致命错误:找不到模块'位置'”Xcode找不到模块

自定义颤振图标位置

VScode 无法找到颤振 sdk 目录

颤振位置堆栈小部件在中心