Функция onChange location продолжает вызываться, даже когда location is stati c (Flutter) - PullRequest
0 голосов
/ 29 марта 2020

Я работаю с пакетом Location 3.0.1 во Flutter. Я хочу слушать изменения местоположения. Мой код (который почти полностью взят из примера 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();
    }
.  .  .

Тем не менее, потоковая подписка запускается довольно часто (примерно раз в 2-3 секунды) ( из-за чего вызывается setState и перестраивается весь экран), даже когда местоположение не меняется (я запускаю этот код на моем эмуляторе, поэтому местоположение должно быть c). Кто-нибудь знает, почему это происходит и как это исправить?

Вывод трепетного доктора:

[✓] 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 Ответ

0 голосов
/ 30 марта 2020

Вы можете скопировать вставить полный код ниже
Поскольку вы поместили код в Widget build вызвать эту проблему
Вы можете сослаться на это https://medium.com/flutter-community/build-a-location-service-in-flutter-367a1b212f7a для создания службы определения местоположения
I сделав несколько изменений, вы можете сразу увидеть полный код
Вы можете использовать StreamProvider вместо await location.getLocation в Widget build Вы можете напрямую использовать location.requestPermission вместо Permission Handler

код snippt

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) {

рабочая демоверсия

enter image description here

полный код

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}'),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...