Показать пины подколлекции firebase на карте — Flutter

У меня есть приложение, которое считывает данные о парковках с базы данных и показывает некоторые метки на карте. Теперь приложение показывает только метки для парковок, но я также хочу добавить на карту метки с каждой отдельной парковки, сохраненной в подколлекции лотов коллекции Parkings. Как я могу это сделать?

maps.dart:

class StoreMap extends StatelessWidget {
  StoreMap({
    Key key,
    @required this.documents,
    @required this.initialPosition,
  }) : super(key: key);

  
  final List<DocumentSnapshot> documents;
  final LatLng initialPosition;
  final Completer<GoogleMapController> _controller = Completer();

  static final CameraPosition _initialPosition = CameraPosition(
    target: LatLng(45.791789, 24.150390),
    zoom: 16,
  );


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
        mapType: MapType.hybrid,
        initialCameraPosition: _initialPosition,
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },
        myLocationEnabled: true,
        markers:documents.map((document) => new Marker(
                  markerId: MarkerId(document.get('name')),
                  position: LatLng(
                    document.get('location').latitude,
                    document.get('location').longitude,
                  ),
                  onTap: () => _changeMap(LatLng(
                    document.get('location').latitude,
                    document.get('location').longitude,
                  )),
                  infoWindow: InfoWindow(
                      title: document.get('name'),
                      snippet: document.get('numberOfLots')),
             icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueViolet)),
                )
            .toSet()
      ),
  floatingActionButton: FloatingActionButton(
        onPressed: _currentLocation,
        child: Icon(Icons.location_searching),
        backgroundColor: Colors.deepPurple[400],
      ),
    );
  }

document.collection (лоты) .get (‘location’). latitude не работает, потому что вы не указали никаких документов после сбора (лотов)   —  person Andreea Purta    schedule 03.09.2020

Запись document.collection (лоты) .document (h6nU1Gyx4Tlb5rpGYi5e) .get (‘location’). Latitude тоже не работает   —  person Andreea Purta    schedule 03.09.2020

См. также:  Flutter Fire Сохраняет порядок по и где запросы вызывают ошибку
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. Andreea Purta

    Причина, по которой document.collection("lots").document("DocumentId").get('location').latitude не работает, заключается в том, что вы не должны передавать имя поля для получения метода. также в вашем коде документ — это просто снимок документа, поэтому вам нужно получить идентификатор этого документа, а затем получить доступ к его подколлекции и поддокументам.

    Вы можете сделать что-то вроде этого:

    //The code below gets the document ids of the parking collection
    //gets access the sub collection "lots" and gets all the documents inside it.
    //and for every sub document, gets the data and prints the latitude of the location field
    for (DocumentSnapshot document in documents){
        String documentId = document.documentId;
        DocumentReference parkingDocReference = 
        Firestore.instance.collection("Parkings").document(documentId);
        parkingDocReference.collection("lots")
        .get((QuerySnapshot subDocuments){
        List<DocumentSnapshot> subDocumentsSnapshots = subDocuments.documents;
        for (DocumentSnapshot subDoc in subDocumentsSnapshots){
             String subDocId = subDoc.documentId;
             parkingDocReference.collection("lots")
             .document(subDocId).get().then((DocumentSnapshot snapshot){ 
                 print(snapshot.data["location"].latitude); //prints the latitude;
             }
      
         }
      });
    
    }
    

    get () вернет Future<DocumentSnapshot>, и поэтому мы используем .then () после get (), чтобы функция запускалась только при получении данных

    Обновление. Чтобы увидеть маркеры на карте, мы помещаем приведенный выше код в функцию, которая возвращает Future<List<Marker>>. когда возвращается результат, вы можете вызвать setState и использовать обновленный список в дереве виджетов.

    Лучше использовать async / await вместо then, поскольку это заставляет программу получать результат из будущее в первую очередь.

    Future<List<Marker>> _createMarkersForLotsAndParkings() async{
       List<Marker> markersList = [];
       int markerId = 0;
       for (DocumentSnapshot document in widget.documents){
        // ignore: deprecated_member_use
        String documentId = document.documentID;
        DocumentReference parkingDocReference = 
        // ignore: deprecated_member_use
        Firestore.instance.collection("Parkings").document(documentId);
        DocumentSnapshot parkingDocRef = await parkingDocReference.get();
        markersList.add(Marker(
                      markerId: MarkerId(markerId.toString()),
                      position: LatLng(parkingDocRef.get('location').latitude,
                          parkingDocRef.get('location').longitude),
                      onTap: () => _changeMap(LatLng(
                          parkingDocRef.get('location').latitude,
                          parkingDocRef.get('location').longitude)),
                      infoWindow: InfoWindow(
                          title: document.get('name'),
                          snippet: document.get('numberOfLots')),
                      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueYellow)),
                );
                markerId++;
        QuerySnapshot subDocuments = await parkingDocReference.collection("lots").get();
        // ignore: deprecated_member_use
        // ignore: deprecated_member_use
        List<DocumentSnapshot> subDocumentsSnapshots = subDocuments.documents;
        for (DocumentSnapshot subDoc in subDocumentsSnapshots){
             // ignore: deprecated_member_use
             String subDocId = subDoc.documentID;
             DocumentSnapshot snapshot = await parkingDocReference.collection("lots")
             // ignore: deprecated_member_use
             .document(subDocId).get();
                print(snapshot.get('location').latitude);
    
                markersList.add(
                  Marker(
                      markerId:MarkerId(markerId.toString()),
                      position: LatLng(snapshot.get('location').latitude,
                          snapshot.get('location').longitude),
                      onTap: () => _changeMap(LatLng(
                          snapshot.get('location').latitude,
                          snapshot.get('location').longitude)),
                      infoWindow: InfoWindow(
                          title: document.get('name'),
                          snippet: document.get('numberOfLots')),
                      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueViolet)),
                );
                markerId++;
    
         }
    
    }
    return Future.value(markersList);
    
    }
    
    
    

    Мы вызываем эту функцию в initState(). Вам необходимо преобразовать StoreMap в StatefullWidget, чтобы иметь возможность вызывать setState и использовать initState:

    
    @override
      void initState() {
        super.initState();
        _createMarkersForLots().then((List<Marker> lotsMarkers){
        setState((){
        markers = lotsMarkers; //rebuilds the screen with the lotsMarkers. make sure to use the markers in your widget tree to see the markers
      });
        
    });
    }
    

    И ваш полный код должен выглядеть примерно так:

    import 'dart:async';
    
    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:flutter/material.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    import 'package:location/location.dart';
    
    class StoreMap extends StatefulWidget {
      StoreMap({
        Key key,
        @required this.documents,
        @required this.initialPosition,
      }) : super(key: key);
    
      final List<DocumentSnapshot> documents;
      final LatLng initialPosition;
      static final CameraPosition _initialPosition = CameraPosition(
        target: LatLng(45.791789, 24.150390),
        zoom: 16,
      );
    
    
      @override
      _StoreMapState createState() => _StoreMapState();
    }
    
    class _StoreMapState extends State<StoreMap> {
      final Completer<GoogleMapController> _controller = Completer();
    
    
    List<Marker> markers = [];
    Future<List<Marker>> _createMarkersForLotsAndParkings() async{
       List<Marker> markersList = [];
       int markerId = 0;
       for (DocumentSnapshot document in widget.documents){
        // ignore: deprecated_member_use
        String documentId = document.documentID;
        DocumentReference parkingDocReference = 
        // ignore: deprecated_member_use
        Firestore.instance.collection("Parkings").document(documentId);
        DocumentSnapshot parkingDocRef = await parkingDocReference.get();
        markersList.add(Marker(
                      markerId: MarkerId(markerId.toString()),
                      position: LatLng(parkingDocRef.get('location').latitude,
                          parkingDocRef.get('location').longitude),
                      onTap: () => _changeMap(LatLng(
                          parkingDocRef.get('location').latitude,
                          parkingDocRef.get('location').longitude)),
                      infoWindow: InfoWindow(
                          title: document.get('name'),
                          snippet: document.get('numberOfLots')),
                      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueYellow)),
                );
                markerId++;
        QuerySnapshot subDocuments = await parkingDocReference.collection("lots").get();
        // ignore: deprecated_member_use
        // ignore: deprecated_member_use
        List<DocumentSnapshot> subDocumentsSnapshots = subDocuments.documents;
        for (DocumentSnapshot subDoc in subDocumentsSnapshots){
             // ignore: deprecated_member_use
             String subDocId = subDoc.documentID;
             DocumentSnapshot snapshot = await parkingDocReference.collection("lots")
             // ignore: deprecated_member_use
             .document(subDocId).get();
                print(snapshot.get('location').latitude);
    
                markersList.add(
                  Marker(
                      markerId:MarkerId(markerId.toString()),
                      position: LatLng(snapshot.get('location').latitude,
                          snapshot.get('location').longitude),
                      onTap: () => _changeMap(LatLng(
                          snapshot.get('location').latitude,
                          snapshot.get('location').longitude)),
                      infoWindow: InfoWindow(
                          title: document.get('name'),
                          snippet: document.get('numberOfLots')),
                      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueViolet)),
                );
                markerId++;
      
         }
    
    }
    return Future.value(markersList);
    
    }
    
    @override
      void initState() {
        super.initState();
        _createMarkersForLotsAndParkings().then((List<Marker> lotsMarkers){
        setState((){
        markers = lotsMarkers; 
      });
        
    });
    }
    
    
      
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: GoogleMap(
            zoomGesturesEnabled: true,
            mapType: MapType.hybrid,
            initialCameraPosition: StoreMap._initialPosition,
            onMapCreated: (GoogleMapController controller) {
              _controller.complete(controller);
            },
            myLocationEnabled: true,
            markers: markers.toSet(),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _currentLocation,
            child: Icon(Icons.location_searching),
            backgroundColor: Colors.deepPurple[400],
          ),
        );
      }
    
      void _currentLocation() async {
        final GoogleMapController controller = await _controller.future;
        LocationData currentLocation;
        var location = new Location();
        try {
          currentLocation = await location.getLocation();
        } on Exception {
          currentLocation = null;
        }
    
        controller.animateCamera(CameraUpdate.newCameraPosition(
          CameraPosition(
            bearing: 0,
            target: LatLng(currentLocation.latitude, currentLocation.longitude),
            zoom: 18.0,
          ),
        ));
      }
    
      _changeMap(LatLng position) async {
        final GoogleMapController controller = await _controller.future;
    
        controller.animateCamera(CameraUpdate.newCameraPosition(
          CameraPosition(
            bearing: 0,
            target: LatLng(position.latitude, position.longitude),
            zoom: 19.4,
          ),
        ));
      }
    }
    
    
    

    Карта Google показывает один маркер для маркеров с одинаковым идентификатором, поэтому мы используем markerId, чтобы присвоить каждому маркеру уникальный идентификатор и увидеть все маркеры.

    Я получаю эту ошибку: метод «коллекция» не определен для типа «DocumentSnapshot». \ NПопробуйте исправить имя на имя существующего метода или определить метод с именем «коллекция». person Andreea Purta; 03.09.2020

    взгляните на мое обновленное решение и проверьте, работает ли оно person Andreea Purta; 04.09.2020

    Я добавил это в функцию. И я могу видеть широту на моей консоли, но я не знаю, как подключить ее к LatLong (…) в маркерах, чтобы отобразить их в пользовательском интерфейсе. person Andreea Purta; 04.09.2020

    вы можете получить координаты с помощью этого кода. Вы также можете создать функцию с тем же кодом, но она должна возвращать список маркеров, поэтому вам нужно создать маркеры в функции. затем используйте этот список и создайте маркеры в дереве виджетов. вы можете вызвать функцию в initState и вызвать setState, когда у вас есть список маркеров person Andreea Purta; 04.09.2020

    Я пробовал это (см. Последнюю добавленную мной треску), но маркеры не появляются. person Andreea Purta; 04.09.2020

    взгляните на мой обновленный ответ и посмотрите, поможет ли он person Andreea Purta; 04.09.2020

    Большое спасибо за ваше терпение и помощь. Они все еще не появляются. Пожалуйста, посмотрите мое последнее обновление. Нет ошибки в консоли отладки. person Andreea Purta; 05.09.2020

    Я думаю, что не назвал маркеры прямо в дереве виджетов person Andreea Purta; 05.09.2020

    Взгляните на stackoverflow.com/questions/55000043/ person Andreea Purta; 05.09.2020

    Я пробовал с маркерами: Установите ‹Marker› .of (маркеры). Еще ничего person Andreea Purta; 05.09.2020

    Позвольте нам продолжить это обсуждение в чате. person Andreea Purta; 05.09.2020

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: