我有一个Flutter应用程序,该应用程序在主屏幕上使用google map。首先,我打电话给Firebase来取代我已经输入的地方。然后,如果用户在地图中加倍,则可以添加一个新地点,这将导致他进入SecondScreen。用户输入标题,故事和照片。我有另一个屏幕,用户可以在其中查看现有标记的信息,也可以在其中删除它。我的问题是,当用户输入或删除标记并返回到主页时,在地图中,这些位置未刷新,并且我看到Firebase不再被调用。我怎么解决这个问题? Firebase在MapsDemo类中被调用 我的代码:
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应用中添加或删除标记时,我的地图没有刷新...知道吗?
答案 0 :(得分:1)
您所有的小部件均为Stateless
,这意味着它们在用户交互时将无法更新或更改。 This tutorial from the Flutter documentation介绍了如何使用Stateful
小部件向您的应用添加交互性,这将解决您的问题。