【问题标题】:Flutter refresh map after come back from second screen从第二个屏幕回来后颤动刷新地图
【发布时间】:2018-11-22 11:40:06
【问题描述】:

我有一个 Flutter 应用程序,在主屏幕上我使用谷歌地图。开始时,我调用 Firebase 来取代我已经输入的位置。然后用户可以在地图中添加一个新位置,这会将他引导到 SecondScreen。用户输入标题、故事和照片。我有另一个屏幕,用户可以在其中查看现有标记的信息,也可以将其删除。我的问题是当用户输入或删除标记并返回主页时,在地图中,这些地方没有刷新,我看到 Firebase 没有再次被调用。我怎么解决这个问题?在 MapsDemo 类中调用 Firebase 我的代码:

import 'dart:ui' as ui;
import  'dart:io';
import 'dart:convert';

import 'package:http/http.dart' as http;

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';

import 'infopage.dart';

void main() {

  GoogleMapController.init();
  final size = MediaQueryData.fromWindow(ui.window).size;
  final GoogleMapOverlayController controller =
      GoogleMapOverlayController.fromSize(
    width: size.width,
    height: size.height,
  );

  final mapController = controller.mapController;
////  Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
////  TODO check if every time I come back the above commands call
//  Firestore.instance.collection('Stories').snapshots().listen((data) =>
//      data.documents.forEach((doc) =>
////Read all the markers from firebase and add them to map
//
//          AddMarkers(mapController, ConvertCoordinates(doc["lat"], doc["lng"]),
//              doc["title"], doc["story"], doc["url"])));



  final Widget mapWidget = GoogleMapOverlay(controller: controller);


  runApp(

    MaterialApp(
      home: new Scaffold(
        appBar: AppBar(
          title: TextField(
            decoration: InputDecoration.collapsed(hintText: 'Search'),
          ),
          actions: <Widget>[
            IconButton(
              icon: const Icon(Icons.my_location),
              onPressed: () async {
                Position position = await Geolocator()
                    .getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
//                Get my current position
                final location = LatLng(position.latitude, position.longitude);
                mapController.markers.clear();
                mapController.addMarker(MarkerOptions(
                    position: location,
                    infoWindowText: InfoWindowText("Here you are!", "Add me"),
                    visible: true));
                mapController.animateCamera(
                  CameraUpdate.newLatLngZoom(location, 20.0),
                );
              },
            ),
          ],
        ),
        body: MapsDemo(mapWidget, controller.mapController),
        floatingActionButton: FloatingActionButton(
          onPressed: () {},
          child: const Icon(Icons.my_location),
        ),
      ),
      navigatorObservers: <NavigatorObserver>[controller.overlayController],
    ),
  );
}

class MapsDemo extends StatelessWidget {
  MapsDemo(this.mapWidget, this.controller);

  final Widget mapWidget;
  final GoogleMapController controller;

  @override
  Widget build(BuildContext context) {
//  Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
//  TODO check if every time I come back the above commands call
    Firestore.instance.collection('Stories').snapshots().listen((data) =>
        data.documents.forEach((doc) =>
//Read all the markers from firebase and add them to map

        AddMarkers(controller, ConvertCoordinates(doc["lat"], doc["lng"]),
            doc["title"], doc["story"], doc["url"])));

    controller.onMarkerTapped.add((Marker marker) async {
//Marker listener open new page info page

      String titlos = marker.options.infoWindowText.title;





      if (titlos != "Here you are!") {
        String story = marker.options.infoWindowText.snippet.split("?")[0];
        String url = marker.options.infoWindowText.snippet.split("?")[1];
        String realUrl = await makeRequest(url);
        String downloadUrl =getDownloadUrl(realUrl,url);

        Navigator.push(
//        Parse title to next page/screen

            context,
            new MaterialPageRoute(
                builder: (context) =>
                    new AboutPage(title: titlos, story: story, url: downloadUrl,)));
      } else {

        Navigator.push(
//        Parse title to next page/screen
            context,
            new MaterialPageRoute(builder: (context) => new SecondScreen(
                marker.options.position.latitude.toString(),
                marker.options.position.longitude.toString())));
      }
    });
    return Center(child: mapWidget);
  }
}

LatLng ConvertCoordinates(String lat, String lng) {
// Convert strings coordinates to LatLng
  return LatLng(double.parse(lat), double.parse(lng));
}

void AddMarkers(GoogleMapController map, LatLng coor, String title,
    String story, String url) {
  map.addMarker(MarkerOptions(
      position: coor, infoWindowText: InfoWindowText(title, '$story'+'?'+'$url')));
}



Future<String> makeRequest(String n) async {
  String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
  String url = '$baseUrl' + '$n';
  var client = new http.Client();
  final response = await client.get(url);


return response.body;
}


String getDownloadUrl(String url, String name){
  String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
  String token =  url.replaceAll("{", "").replaceAll("}", "").split('"downloadTokens": ')[1].replaceAll('"', '');
  return '$baseUrl'+'$name'+"?alt=media&token="+'$token';

}

class SecondScreen extends StatelessWidget {
  final String lat;
  final String lng;
//  final String image_name;
  final titleC = TextEditingController();
  final storyC = TextEditingController();
  static final String image_name = Uuid().v1();




  SecondScreen(this.lat, this.lng,);
  Future getImage() async {
    var image = await ImagePicker.pickImage(source: ImageSource.camera);
    final StorageReference firebaseStorageRef =
    FirebaseStorage.instance.ref().child(image_name);
    final StorageUploadTask task =
    firebaseStorageRef.putFile(image);
  }

  uploadFirebase(){

    var map= {
      "title":titleC.text,
      "story":storyC.text,
      "url":image_name,
      "lat":lat,
      "lng":lng
    };

    Firestore.instance.collection('Stories').document()
        .setData(map);
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: Center(
        child: new Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
          new TextField (
            controller: titleC,
          ),
      new TextField(
        controller: storyC,
      ),
          new RaisedButton(
            onPressed: () => getImage(),
            child: new Text('Take photo'),

          ),
          new RaisedButton(
            onPressed: () => uploadFirebase(),
            child: new Text('Confirm'),

          )

    ])
      ),
    );
  }
}

[编辑] 我把我的代码改成这个,

import 'dart:ui' as ui;
import  'dart:io';
import 'dart:convert';

import 'package:http/http.dart' as http;

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';

import 'infopage.dart';

void main() {

  GoogleMapController.init();
  final size = MediaQueryData.fromWindow(ui.window).size;
  final GoogleMapOverlayController controller =
  GoogleMapOverlayController.fromSize(
    width: size.width,
    height: size.height,
  );

  final mapController = controller.mapController;
////  Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
////  TODO check if every time I come back the above commands call
//  Firestore.instance.collection('Stories').snapshots().listen((data) =>
//      data.documents.forEach((doc) =>
////Read all the markers from firebase and add them to map
//
//          AddMarkers(mapController, ConvertCoordinates(doc["lat"], doc["lng"]),
//              doc["title"], doc["story"], doc["url"])));



  final Widget mapWidget = GoogleMapOverlay(controller: controller);


  runApp(

    MaterialApp(
      home: new Scaffold(
        appBar: AppBar(
          title: TextField(
            decoration: InputDecoration.collapsed(hintText: 'Search'),
          ),
          actions: <Widget>[
            IconButton(
              icon: const Icon(Icons.my_location),
              onPressed: () async {
                Position position = await Geolocator()
                    .getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
//                Get my current position
                final location = LatLng(position.latitude, position.longitude);
                mapController.markers.clear();
                mapController.addMarker(MarkerOptions(
                    position: location,
                    infoWindowText: InfoWindowText("Here you are!", "Add me"),
                    visible: true,draggable: true));
                mapController.animateCamera(
                  CameraUpdate.newLatLngZoom(location, 20.0),
                );
              },
            ),
            IconButton(
              icon: const Icon(Icons.refresh),
              onPressed: () {RefreshIt(mapController);},
            )
          ],
        ),
        body: _MapDemo(mapWidget:mapWidget, controller:controller.mapController),

      ),
      navigatorObservers: <NavigatorObserver>[controller.overlayController],
    ),
  );
}
class _MapDemo extends StatefulWidget{
final Widget mapWidget;
final GoogleMapController controller;

const _MapDemo({Key key, this.mapWidget, this.controller}) : super(key: key);
@override
MapsDemo createState() => MapsDemo(this.mapWidget, this.controller);



}
class MapsDemo extends State<_MapDemo> {
  MapsDemo(this.mapWidget, this.controller);

  final Widget mapWidget;
  final GoogleMapController controller;

  @override
  Widget build(BuildContext context) {
//  Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
  controller.markers.clear();
//  TODO check if every time I come back the above commands call
    Firestore.instance.collection('Stories').snapshots().listen((data) =>
        data.documents.forEach((doc) =>
//Read all the markers from firebase and add them to map

        AddMarkers(controller, ConvertCoordinates(doc["lat"], doc["lng"]),
            doc["title"], doc["story"], doc["url"])));

    controller.onMarkerTapped.add((Marker marker) async {
//Marker listener open new page info page

      String titlos = marker.options.infoWindowText.title;





      if (titlos != "Here you are!") {
        String story = marker.options.infoWindowText.snippet.split("?")[0];
        String url = marker.options.infoWindowText.snippet.split("?")[1];
        String realUrl = await makeRequest(url);
        String downloadUrl =getDownloadUrl(realUrl,url);

        Navigator.push(
//        Parse title to next page/screen

            context,
            new MaterialPageRoute(
                builder: (context) =>
                new AboutPage(title: titlos, story: story, url: downloadUrl,)));
      } else {

        Navigator.push(
//        Parse title to next page/screen
            context,
            new MaterialPageRoute(builder: (context) => new _SecondScreen(
                lat:marker.options.position.latitude.toString(),
                lng:marker.options.position.longitude.toString())));
      }
    });
    return Center(child: mapWidget);
  }
}

LatLng ConvertCoordinates(String lat, String lng) {
// Convert strings coordinates to LatLng
  return LatLng(double.parse(lat), double.parse(lng));
}

void AddMarkers(GoogleMapController map, LatLng coor, String title,
    String story, String url) {
  map.addMarker(MarkerOptions(
      position: coor, infoWindowText: InfoWindowText(title, '$story'+'?'+'$url')));
}

void RefreshIt(GoogleMapController mapController){
//TODO Refresh the map via this float button



}

Future<String> makeRequest(String n) async {
  String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
  String url = '$baseUrl' + '$n';
  var client = new http.Client();
  final response = await client.get(url);


  return response.body;
}


String getDownloadUrl(String url, String name){
  String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
  String token =  url.replaceAll("{", "").replaceAll("}", "").split('"downloadTokens": ')[1].replaceAll('"', '');
  return '$baseUrl'+'$name'+"?alt=media&token="+'$token';

}
class _SecondScreen extends StatefulWidget{
  final String lat;
  final String lng;

  const _SecondScreen({Key key, this.lat, this.lng}) : super(key: key);
  @override
  SecondScreen createState() => SecondScreen(this.lat, this.lng);



}
class SecondScreen extends State<_SecondScreen> {
  final String lat;
  final String lng;
//  final String image_name;
  final titleC = TextEditingController();
  final storyC = TextEditingController();
  static final String image_name = Uuid().v1();




  SecondScreen(this.lat, this.lng,);
  Future getImage() async {
    var image = await ImagePicker.pickImage(source: ImageSource.camera);
    final StorageReference firebaseStorageRef =
    FirebaseStorage.instance.ref().child(image_name);
    final StorageUploadTask task =
    firebaseStorageRef.putFile(image);
  }

  uploadFirebase(){

    var map= {
      "title":titleC.text,
      "story":storyC.text,
      "url":image_name,
      "lat":lat,
      "lng":lng
    };

    Firestore.instance.collection('Stories').document()
        .setData(map);
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Input Screen"),
      ),
      body: Center(
          child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new TextField (
                  controller: titleC,
                ),
                new TextField(
                  controller: storyC,
                ),
                new RaisedButton(
                  onPressed: () => getImage(),
                  child: new Text('Take photo'),

                ),
                new RaisedButton(
                  onPressed: () => uploadFirebase(),
                  child: new Text('Confirm'),

                )

              ])
      ),
    );
  }
}

我的 firebase 与具有相同概念的网站共享,当我在网站中添加内容时,新标记会出现在我的 Flutter 应用程序中,但当我删除标记时不会出现。另一方面,当我在 Flutter 应用程序中添加或删除标记时,我的地图没有得到任何刷新......有什么想法吗?

【问题讨论】:

  • 这个问题有没有得到解决/回答?如果是这样,你做了什么?

标签: firebase google-maps dart flutter maps


【解决方案1】:

我从后台恢复应用程序后设置了 mapStyle,它对我有用:

mapController.setMapStyle("[]");

【讨论】:

    【解决方案2】:

    您的所有小部件都是Stateless,这意味着它们将无法在用户交互时更新或更改。 This tutorial from the Flutter documentation 介绍了如何使用 Stateful 小部件为您的应用添加交互性,这将解决您的问题。

    【讨论】:

      猜你喜欢
      • 2020-12-20
      • 1970-01-01
      • 2023-01-23
      • 1970-01-01
      • 2023-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      相关资源
      最近更新 更多